<HTML><HEAD><!-- This HTML file has been created by texi2html 1.51     from unix.texinfo on 23 August 2001 --><TITLE>The unix programming environment</TITLE></HEAD><BODY><H1>The unix programming environment</H1><H2>Edition 2.2, August 2001</H2><ADDRESS>Mark Burgess</ADDRESS><ADDRESS>Centre of Science and Technology</ADDRESS><ADDRESS>Faculty of Engineering, Oslo College</ADDRESS><P><P><HR><P><H1><A NAME="SEC1" HREF="unix_toc.html#TOC1">Foreword</A></H1><P> This is a revised version of the UNIX compendium which isavailable in printed form and online via the WWW and infohypertext readers. It forms the basis for a one or two semestercourse in UNIX. The most up-to-date version of this manualcan be found at </P><PRE>http://www.iu.hio.no/~mark/unix/unix.html.</PRE><P>It is a reference guide which contains enough to help you to find whatyou need from other sources. It is not (and probably can never be)a complete and self-contained work. Certain topics are coveredin more detail than others. Some topics are included for futurereference and are not intended to be part of an introductory course,but will probably be useful later. The chapter on X11 programminghas been deleted for the time being.</P><P>Comments to Mark.Burgess@iu.hio.no Oslo, August 2001 </P><H1><A NAME="SEC2" HREF="unix_toc.html#TOC2">Welcome</A></H1><P>If you are coming to unix for the first time, from a Windows orMacIntosh environment, be prepared for a rather different culture thanthe one you are used to. UNIX is not about `products' and off-the-shelfsoftware, it is about open standards, free software and the ability tochange just about everything.</P><UL><LI>What you personally might perceive as user friendliness in othersystems, others might perceive as annoying time wasting. UNIX offers youjust about every level of friendliness and unfriendliness, if you chooseyour programs right. In this book, we take the programmer's point ofview.<LI>UNIX is about functionality, not about simplicity. Be preparedfor powerful, not necessarily `simple' solutions.</UL><P>You should approach UNIX the way you should approach any newsystem: with an open mind. The journey begins...</P><H1><A NAME="SEC3" HREF="unix_toc.html#TOC3">Overview</A></H1><P> <EM>In this manual the word "host" is used to refer to a single computersystem -- i.e.  a single machine which has a name termed its "hostname".</EM></P><P> </P><H2><A NAME="SEC4" HREF="unix_toc.html#TOC4">What is unix?</A></H2><P><A NAME="IDX1"></A><A NAME="IDX2"></A>UNIX is one of the most important operating system in usetoday, perhaps even <EM>the</EM> most important. Since its inventionaround the beginning of the 1970s it has been an object of continualresearch and development. UNIX is not popular because it is the bestoperating system one could imagine, but because it is an extremelyflexible system which is easy to extend and modify. It is an idealplatform for developing new ideas.  </P><P>Much of the success of UNIX may be attributed to the rapid pace of itsdevelopment (a development to which all of its users have been able tocontribute) its efficiency at running programs and the many powerfultools which have been written for it over the years, such as the Cprogramming language, <CODE>make</CODE>, shell, <CODE>lex</CODE> and <CODE>yacc</CODE> andmany others.  UNIX was written by programmers for programmers. It ispopular in situations where a lot of computing power is required and fordatabase applications, where timesharing is critical. In contrast tosome operating systems, UNIX performs equally well on large scalecomputers (with many processors) and small computers which fit in yoursuitcase!</P><P>All of the basic mechanisms required of a multi-user operating systemare present in UNIX. During the last few years it has become ever morepopular and has formed the basis of newer, though less mature, systemslike NT.  One reason for this that now computers have now become powerfulenough to run UNIX effectively.  UNIX places burdens on the resources ofa computer, since it expects to be able to run potentially many programssimultaneously.</P><P><A NAME="IDX3"></A>If you are coming to UNIX from Windows or DOS you may well be used to usingapplications software or helpful interactive utilities to solve everyproblem. UNIX is not usually like this: the operating system has muchgreater functionality and provides the possibilities for making yourown, so it is less common to find applications software which implementsthe same things. In UNIX you are usually asked to learn a languagein order to express exactly what you want. This is much more powerfulthan menu systems, but it is harder to learn</P><P>UNIX has long been in the hands of academics who areused to making their own applications or writing their own programs,whereas as the Windows world has been driven by businesses who are willingto spend money on software.  For that reason commercial UNIX software isoften very expensive and therefore not available at this college. On theother hand, the flexibility of UNIX means that it is easy to writeprograms and it is possible to fetch gigabytes of <EM>free software</EM> from theInternet to suit your needs. It may not look exactly like what you are used toon your PC, but then you have to remember that UNIX users are adifferent kind of animal altogether</P><P>Like all operating systems, UNIX has many faults. The biggest problemfor any operating system is that it evolves without being redesigned.Operating systems evolve as more and more patches and hacks are appliedto solve day-to-day problems. The result is either a mess which workssomehow (like UNIX) or a blank refusal to change (like DOS orthe MacIntosh, prior to MacOS X, which is based on BSD UNIX).  From a practical perspective, UNIX is important andsuccessful because it is a multi-process system which</P><UL><LI>has an enormous functionality built in, and the capacity toadapt itself to changing technologies,<LI>is relatively portable,<LI>is good at sharing resources (but not so good at security),<LI>has tools which are each developed to do <EM>one thing well</EM>,<LI>allows these tools to be combined in every imaginable way,using pipes and channeling of data streams,<LI>incorporates networking almost trivially, because all the rightmechanisms are already there for providing services and sharing,building client-server pairs etc,.<LI>it is very adaptable and is often used to developnew ideas because of the rich variety of tools it possesses.</UL><P>UNIX has some problems: it is old, it contains a lot of rubbish which noone ever bothered to throw away. Although it develops quickly (at lightspeed compared to either DOS/Windows or MacIntosh) the user interface has beenthe slowest thing to change. UNIX is not user-friendly for beginners, itis user-friendly for advanced users: it is made for users who<EM>know</EM> about computing. It sometimes makes simple things difficult,but above all it makes things possible!</P><P>The aim of this introduction is to</P><UL><LI>introduce the unix system basics and user interface,<LI>develop the unix philosophy of using and combining tools,<LI>learn how to make new tools and write software,<LI>learn how to understand existing software.</UL><P>To accomplish this task, we must first learn something aboutthe shell language (the way in which UNIX starts programs). Later we shalllearn how to solve more complex problems using Perl and C.Each of these is a language which can be used to put UNIX towork. We must also learn when to use which tool, so thatwe do not waste time and effort. Typical uses for these different interfaces are</P><DL COMPACT><DT><EM>shell</EM><DD>Command line interaction, making scripts which performs simplejobs such as running programs, installing new software,simple system configuration and administration.<A NAME="IDX4"></A><DT><EM>perl</EM><DD>Text interpretation, text formatting, output filters, mailrobots, WWW cgi (common gateway interface) scripts in forms,password testing, simple database manipulation, simple client-serverapplications.<A NAME="IDX5"></A><DT><EM>C</EM><DD>Nearly all of UNIX is written in C. Any program which cannotbe solved quickly using shell or perl can be written in C.One advantage is that C is a compiled language and many simpleerrors can be caught at compile time.<A NAME="IDX6"></A></DL><P>Much of UNIX's recent popularity has been a result of its networkingabilities: UNIX is the backbone of the Internet. No other widelyavailable system could keep the Internet alive today. GNU/Linuxis a free/open source re-write of the UNIX operating system, whichmany enhancements. While GNU/Linux is not "rocket science" tocomputer experts, it has distilled the essence of UNIX and placed itin the hands of everyone. It runs on wrist watches and mainframecomputers. Like it or loathe it, GNU/Linux is probably the most importantsingle development in computer operating systems for many years.</P><P>Once you have mastered the UNIX interface and philosophy youwill find that i) the PC and MacIntosh window environments might seemto be easy to use, but are simplistic and primitive by comparison; ii) UNIX is farfrom being the perfect operating system--it has a whole differentset of problems and flaws.<A NAME="IDX7"></A><A NAME="IDX8"></A><A NAME="IDX9"></A></P><P>The operating system of the future will not be UNIX or GNU/Linux as we see it today(hopefully), nor will is be DOS or MacIntosh, but one thing is forcertain: it will owe a lot to the UNIX operating system and will containmany of the tools and mechanisms we shall describe below.</P><P> <H2><A NAME="SEC5" HREF="unix_toc.html#TOC5">Flavours of unix</A></H2><P><A NAME="IDX10"></A><A NAME="IDX11"></A><A NAME="IDX12"></A><A NAME="IDX13"></A></P><P>UNIX is not a single operating system. It has branched out in manydifferent directions since it was introduced by AT&#38;T. The mostimportant <SAMP>`fork()'</SAMP> in its history happened early on when theuniversity of Berkeley, California created the BSD (Berkeley SoftwareDistribution), adding network support and the C-shell.</P><P>Here are some ofthe most common implementations of unix.</P><DL COMPACT><DT><EM>BSD:</EM><DD> Berkeley, BSD<DT><EM>SunOS:</EM><DD>Sun Microsystems, BSD/sys 5<DT><EM>Solaris:</EM><DD>Sun Microsystems,  Sys 5/BSD<DT><EM>Ultrix:</EM><DD>Digital Equipment Corporation, BSD<DT><EM>OSF 1:</EM><DD>Digital Equipment Corporation, BSD/sys 5<DT><EM>HPUX:</EM><DD>Hewlett-Packard, Sys 5<DT><EM>AIX:</EM><DD>IBM, Sys 5 / BSD<DT><EM>IRIX:</EM><DD>Silicon Graphics, Sys 5<DT><EM>GNU/Linux:</EM><DD>GNU, BSD/Posix</DL><H2><A NAME="SEC6" HREF="unix_toc.html#TOC6">How to use this reference guide</A></H2><P>This programming guide is something between a user manual and a tutorial.The information contained here should be sufficient to get you startedwith the unix system, but it is far from complete.</P><P>To use this programming guide, you will need to work through the basicsfrom each chapter. You will find that there is much more information here thanyou need straight away, so try not to be overwhelmed by the amount of material.Use the contents and the indices at the back to find the informationyou need. If you are following a one-semester UNIX course, you shouldprobably concentrate on the following:</P><UL><LI>The remainder of this introduction<LI>The detailed knowledge of the Bash shell<LI>A detailed knowledge of Perl, guided by chapter 6. This chapter providespointers on how to get started in perl. It is not a substitute for theperl book.<LI>A sound appreciation of chapter 8 on network programming.</UL><P>The <EM>only</EM> way to learn UNIX is to sit down and try it. As with anynew thing, it is a pain to get started, but once you are started, youwill probably come to agree that UNIX contains a wealth of possibilities,perhaps more than you had ever though was possible or useful!</P><P>One of the advantages of the UNIX system is that the entire UNIX manualis available on-line. You should get used to looking for information inthe online manual pages. For instance, suppose you do not rememberhow to create a new directory, you could do the following:</P><PRE>nexus% man -k dirdir             ls (1)          - list contents of directoriesdirname         dirname (1)     - strip non-directory suffix from file namedirs            bash (1)        - bash built-in commands, see bash(1)find            find (1)        - search for files in a directory hierarchyls              ls (1)          - list contents of directoriesmkdir           mkdir (1)       - make directoriespwd             pwd (1)         - print name of current/working directoryrmdir           rmdir (1)       - remove empty directories</PRE><P><A NAME="IDX14"></A><A NAME="IDX15"></A><A NAME="IDX16"></A><A NAME="IDX17"></A><A NAME="IDX18"></A><A NAME="IDX19"></A><A NAME="IDX20"></A>The <SAMP>`man -k'</SAMP> command looks for a keyword in the manual and listsall the references it finds. The command <SAMP>`apropos'</SAMP> is completelyequivalent to <SAMP>`man -k'</SAMP>.  Having discovered that the command tocreate a directory is <SAMP>`mkdir'</SAMP> you can now look up the specificmanual page on <SAMP>`mkdir'</SAMP> to find out how to use it:</P><PRE>man mkdir</PRE><P>Some but no all of the UNIX commands also have a help option which isactivated with the <SAMP>`-h'</SAMP> or <SAMP>`--help'</SAMP> command-line option.<A NAME="IDX21"></A><A NAME="IDX22"></A><A NAME="IDX23"></A></P><PRE>dax% mkdir --helpUsage: mkdir [OPTION] DIRECTORY...   -p, --parents     no error if existing, make parent directories as needed  -m, --mode=MODE   set permission mode (as in chmod), not 0777 - umask      --help        display this help and exit      --version     output version information and exitdax%  </PRE><P> <H2><A NAME="SEC7" HREF="unix_toc.html#TOC7">NEVER-DO's in UNIX</A></H2><P><A NAME="IDX24"></A></P><P>There are some things that you should never do in UNIX. Some of thesewill cause you more serious problemsthan others. You can make your own list as you discover more.</P><UL><LI>You should NEVER EVER switch off the power on a UNIX computer unless youknow what you are doing.  A UNIX machine is not like a PC runningDOS. Even when you are not doing anything, the system is working in thebackground. If you switch off the power, you could interrupt the systemwhile it is writing to the disk drive and destroy your disk. You mustalso remember that several users might be using the system even thoughyou cannot see them: they do not have to be sitting at the machine, theycould be logged in over the network. If you switch off the power, youmight ruin their valuable work.<LI>Once you have deleted a UNIX file using <CODE>rm</CODE> it is impossibleto recover it! Don't use wildcards with <CODE>rm</CODE> without thinkingquite carefully about what you are doing! It has happened to very manyusers throughout the history of UNIX that one tries to type<PRE>rm *~</PRE>but instead, by a slip of the hand, one writes<PRE>rm * ~</PRE>UNIX then takes these wildcards in turn, so that the first command is<CODE>rm *</CODE> which deletes all of your files! BE CAREFUL!<A NAME="IDX25"></A><A NAME="IDX26"></A><LI> Don't ever call a program or an important file <TT>`core'</TT>. Manyscripts go around deleting files called <TT>`core'</TT> because the, when aprogram crashes, UNIX dumps the entire kernel image to a file called<TT>`core'</TT> and these files use up a lot of disk space. If you call afile <TT>`core'</TT> it might get deleted!<A NAME="IDX27"></A><LI> Don't call test programs <CODE>test</CODE>. There is a UNIX commandwhich is already called test and chances are that when you try torun your program you will start the UNIX command instead. Thiscan cause a lot of confusion because the UNIX command doesn't seemto do very much at all!</UL><P><A NAME="IDX28"></A><A NAME="IDX29"></A></P><P> <H2><A NAME="SEC8" HREF="unix_toc.html#TOC8">What you should know before starting</A></H2><P> </P><H3><A NAME="SEC9" HREF="unix_toc.html#TOC9">One library: several interfaces</A></H3><P>The core of unix is the library of functions (written in C) whichaccess the system. Everything you do on a unix system goes throughthis set of functions. However, you can choose your own interfaceto these library functions. UNIX has very many different interfacesto its libraries in the form of languages and command interpreters.</P><P>You can use the functions directly in C, or you can use commandprograms like <SAMP>`ls'</SAMP>, <SAMP>`cd'</SAMP> etc. These functions justprovide a simple user interface to the C calls. You can also usea variety of `script' languages: C-shell, Bourne shell, Perl, Tcl, scheme.You choose the interface which solves your problem most easily.</P><P> </P><H3><A NAME="SEC10" HREF="unix_toc.html#TOC10">UNIX commands are files</A></H3><P><A NAME="IDX30"></A><A NAME="IDX31"></A><A NAME="IDX32"></A></P><P>With the exception of a few simple commands which are built into the commandinterpreter (shell), all unix commands and programs consist ofexecutable files. In other words, there is a separate executable file for each command. This makes it extremely simpleto add new commands to the system. One simply makes a program withthe desired name and places it in the appropriate directory.</P><P><A NAME="IDX33"></A><A NAME="IDX34"></A><A NAME="IDX35"></A>UNIX commands live in special directories(usually called <CODE>bin</CODE> for binary files). The location ofthese directories is recorded in a variable called <CODE>path</CODE> or<CODE>PATH</CODE> which is used by the system to search forbinaries. We shall return to this in more detail in later chapters.</P><P> <H3><A NAME="SEC11" HREF="unix_toc.html#TOC11">Kernel and Shell</A></H3><P><A NAME="IDX36"></A><A NAME="IDX37"></A>Since users cannot command the kernel directly, UNIX has a command languageknown as the <EM>shell</EM>. The word shell implies a layer around thekernel. A shell is a user interface, or command interpreter. </P><P>There are two main versions of the shell, plus a number of enhancements.</P><DL COMPACT><DT><EM>/bin/sh</EM><DD>The Bourne Shell. The shell is most often used for writing system scripts. It is part of the original unix system.<A NAME="IDX38"></A><A NAME="IDX39"></A><A NAME="IDX40"></A><DT><EM>/bin/csh</EM><DD>The C-shell. This was added to unix by the Berkeley workers.The commands and syntax resemble C code. C-shell is better suited forinteractive work than the Bourne shell.<A NAME="IDX41"></A><A NAME="IDX42"></A><A NAME="IDX43"></A></DL><P><A NAME="IDX44"></A><A NAME="IDX45"></A><A NAME="IDX46"></A>The program <CODE>tcsh</CODE> is a public-domain enhancement of the csh and isin common use. Two improved versions of the Bourne shell also exist:<CODE>ksh</CODE>, the Korn shell and <CODE>bash</CODE>, the Bourne-again shell.</P><P>Although the shells are mainly tools for typing in commands (which areexecutable files to be loaded and run), they contain features such asaliases, a command history, wildcard-expansions and job controlfunctions which provide a comfortable user environment.</P><P> <H3><A NAME="SEC12" HREF="unix_toc.html#TOC12">The role of C</A></H3><P><A NAME="IDX47"></A><A NAME="IDX48"></A></P><P>Most of the unix kernel and daemons are written in the C programminglanguage <A NAME="DOCF1" HREF="unix_foot.html#FOOT1">(1)</A>.  Calls to the kernel and toservices are made through functions in the standard C library. Thecommands like <CODE>chmod</CODE>, <CODE>mkdir</CODE> and <CODE>cd</CODE> are all Cfunctions. The binary files of the same name <CODE>/bin/chmod</CODE>,<CODE>/bin/mkdir</CODE> etc. are just trivial "wrapper" programs for these Cfunctions.<A NAME="IDX49"></A><A NAME="IDX50"></A><A NAME="IDX51"></A></P><P>Until <EM>Solaris 2</EM>, the C compiler was a standard part of the UNIXoperating system, thus C is the most natural language to program inin a UNIX environment. Some tools are provided for C programmers:</P><DL COMPACT><DT><EM>dbx</EM><DD>A symbolic debugger. Also <EM>gdb</EM>, <EM>xxgdb</EM> <EM>ddd</EM>.<A NAME="IDX52"></A><DT><EM>make</EM><DD>A development tool for compiling large programs.<A NAME="IDX53"></A><DT><EM>lex</EM><DD>A `lexer'. A program which generates C code to recognizewords of text.<A NAME="IDX54"></A><DT><EM>yacc</EM><DD>A `parser'. This is a tool which generates C code forchecking the syntax of groups of textual words.<A NAME="IDX55"></A><DT><EM>rpcgen</EM><DD>A protocol compiler which generates C code from a higherlevel language, for programming RPC applications.<A NAME="IDX56"></A></DL><P> <H3><A NAME="SEC13" HREF="unix_toc.html#TOC13">Stdin, stdout, stderr</A></H3><P>UNIX has three logical <EM>streams</EM> or <EM>files</EM> which are alwaysopen and are available to any program.</P><P><A NAME="IDX57"></A><A NAME="IDX58"></A><A NAME="IDX59"></A><A NAME="IDX60"></A><A NAME="IDX61"></A><A NAME="IDX62"></A><A NAME="IDX63"></A></P><DL COMPACT><DT><EM>stdin</EM><DD>The standard input - file descriptor 0.<DT><EM>stdout</EM><DD>The standard output - file descriptor 1.<DT><EM>stderr</EM><DD>The standard error - file descriptor 2.</DL><P>The names are a part of the C language and are defined aspointers of type <CODE>FILE</CODE>.</P><PRE>#include &#60;stdio.h&#62;/* FILE *stdin, *stdout, *stderr; */fprintf(stderr,"This is an error message!\n");</PRE><P>The names are `logical' in the sense that they do not refer toa particular device, or a particular place for information to come from or go. Their role is analogous to the `.' and `..'directories in the filesystem. Programs can write to thesefiles without worrying about where the information comes from orgoes to. The user can personally define these places by<EM>redirecting standard I/O</EM>. This is discussed in the nextchapter.<A NAME="IDX64"></A><A NAME="IDX65"></A><A NAME="IDX66"></A><A NAME="IDX67"></A><A NAME="IDX68"></A></P><P>A separate stream is kept for error messages so that error outputdoes not get mixed up with a program's intended output.</P><H2><A NAME="SEC14" HREF="unix_toc.html#TOC14">The superuser (root) and <EM>nobody</EM></A></H2><P>When logged onto a UNIX system directly, the user whose name is<CODE>root</CODE> has unlimited access to the files on the system. <CODE>root</CODE>can also become any other user without having to give apassword. <CODE>root</CODE> is reserved for the system administrator or<EM>trusted users</EM>.<A NAME="IDX69"></A><A NAME="IDX70"></A></P><P>Certain commands are forbidden to normal users. For example, a regularuser should not be able to halt the system, or change the ownershipof files (see next paragraph). These things are reserved for the<CODE>root</CODE> or <EM>superuser</EM>.</P><P>In a networked environment, <CODE>root</CODE> has no automatic authority onremote machines. This is to prevent the system administrator of onemachine in Canada from being able to edit files on another in China.  Heor she must log in directly and supply a password in order to gainaccess privileges. On a network where files are often accessible inprinciple to anyone, the username <CODE>root</CODE> gets mapped to the user<CODE>nobody</CODE>, who has no rights at all.<A NAME="IDX71"></A></P><H2><A NAME="SEC15" HREF="unix_toc.html#TOC15">The file hierarchy</A></H2><P><A NAME="IDX72"></A><A NAME="IDX73"></A></P><P>UNIX has a hierarchical filesystem, which makes use of directories andsub-directories to form a tree. The root of the tree is called the rootfilesystem or `/'.  Although the details of where every file is locateddiffer for different versions of unix, some basic features are thesame. The main sub-directories of the root directory together with themost important file are shown in the figure. Their contents are asfollows.</P><DL COMPACT><DT><TT>`/bin'</TT><DD>Executable (binary) programs. On most systems this isa separate directory to /usr/bin. In SunOS, this is a pointer (link) to/usr/bin.<A NAME="IDX74"></A><DT><TT>`/etc'</TT><DD>Miscellaneous programs and configuration files. This directoryhas become very messy over the history of UNIX and has become a dumpingground for almost anything. Recent versions of unix have begun totidy up this directory by creating subdirectories <TT>`/etc/mail'</TT>,<TT>`/etc/services'</TT> etc!<A NAME="IDX75"></A><DT><TT>`/usr'</TT><DD>This contains the main meat of UNIX. This is where application softwarelives, together with all of the basic libraries used by the OS.<A NAME="IDX76"></A><DT><TT>`/usr/bin'</TT><DD>More executables from the OS.<A NAME="IDX77"></A><DT><TT>`/usr/local'</TT><DD>This is where users' custom software is normally added.<A NAME="IDX78"></A><DT><TT>`/sbin'</TT><DD>A special area for statically linked system binaries.  They areplaced here to distinguish commands used solely by thesystem administrator from user commands and so that they lieon the system root partition where they are guaranteed to beaccessible during booting.<A NAME="IDX79"></A><DT><TT>`/sys'</TT><DD>This holds the configuration data which go to build thesystem kernel. (See below.)<A NAME="IDX80"></A><DT><TT>`/export'</TT><DD>Network servers only use this. This contains the disk space set aside forclient machines which do not have their own disks. It is like a `virtual disk'for diskless clients.<A NAME="IDX81"></A><DT><TT>`/dev, /devices'</TT><DD>A place where all the `logical devices' are collected. These arecalled `device nodes' in unix and are created by <CODE>mknod</CODE>. Logicaldevices are UNIX's official entry points for writing to devices. For instance,<CODE>/dev/console</CODE> is a route to the system console, while <CODE>/dev/kmem</CODE>is a route for reading kernel memory. Device nodes enable devices to betreated as though they were files.<A NAME="IDX82"></A><A NAME="IDX83"></A><DT><TT>`/home'</TT><DD>(Called <EM>/users</EM> on some systems.) Each user has a separate logindirectory where files can be kept. These are normally stored under<CODE>/home</CODE> by some convention decided by the system administrator.<A NAME="IDX84"></A><A NAME="IDX85"></A><DT><TT>`/var'</TT><DD>System 5 and mixed systems have a separate directory for spooling. Underold BSD systems, <CODE>/usr/spool</CODE> contains spool queues and systemdata.  <CODE>/var/spool</CODE> and <CODE>/var/adm</CODE> etc are used for holdingqueues and system log files.<A NAME="IDX86"></A><A NAME="IDX87"></A><A NAME="IDX88"></A><DT><TT>`/vmunix'</TT><DD>This is the program code for the unix <EM>kernel</EM> (see below). On HPUX systems with file is called <TT>`hp-ux'</TT>. Onlinux it is called <TT>`linux'</TT>.<A NAME="IDX89"></A><A NAME="IDX90"></A><DT><TT>`/kernel'</TT><DD>On newer systems the kernel is built up from a number of moduleswhich are placed in this directory.</DL><P>Every unix directory contains two `virtual' directories markedby a single dot and two dots. </P><PRE>ls -a.   ..</PRE><P><A NAME="IDX91"></A><A NAME="IDX92"></A></P><P>The single dot represents the directory one is already in (the currentdirectory). The double dots mean the directory one level up the treefrom the current location. Thus, if one writes</P><PRE>cd /usr/localcd ..</PRE><P>the final directory is <CODE>/usr</CODE>. The single dot is very useful inC programming if one wishes to read `the current directory'. Sincethis is always called `.' there is no need to keep track of what thecurrent directory really is.</P><P>`.' and `..' are `hard links' to the truedirectories.<A NAME="IDX93"></A></P><H2><A NAME="SEC16" HREF="unix_toc.html#TOC16">Symbolic links</A></H2><P><A NAME="IDX94"></A><A NAME="IDX95"></A><A NAME="IDX96"></A><A NAME="IDX97"></A></P><P>A symbolic link is a pointer or an alias to another file. The command<PRE>ln -s fromfile /other/directory/tolink</PRE><P>makes the file <CODE>fromfile</CODE> appear to exist at <CODE>/other/directory/tolink</CODE>simultaneously. The file is not copied, it merely appears to be apart of the file tree in two places. Symbolic links can be made toboth files and directories.</P><P>A symbolic link is just a small file which contains the name of the realfile one is interested in. It cannot be opened like an ordinary file,but may be read with the C call <CODE>readlink()</CODE> See section <A HREF="unix.html#SEC174">lstat and readlink</A>.If we remove the file a symbolic linkpoints to, the link remains -- it just points nowhere.</P><H2><A NAME="SEC17" HREF="unix_toc.html#TOC17">Hard links</A></H2><P><A NAME="IDX98"></A><A NAME="IDX99"></A></P><P>A <EM>hard link</EM> is a duplicate <EM>inode</EM> in the filesystem whichis in every way equivalent to the original file inode.  If a file ispointed to by a hard link, it cannot be removed until the link isremoved.  If a file has @math{n} hard links -- all of them must be removedbefore the file can be removed.  The number of hard links to a file isstored in the filesystem <EM>index node</EM> for the file.<A NAME="IDX100"></A><A NAME="IDX101"></A></P><H1><A NAME="SEC18" HREF="unix_toc.html#TOC18">Getting started</A></H1><P>If you have never met unix, or another multiuser system before,then you might find the idea daunting. There are several thingsyou should know. </P><H2><A NAME="SEC19" HREF="unix_toc.html#TOC19">Logging in</A></H2><P>Each time you use unix you must log on to the system by typing ausername and a password.  Your login name is sometimes called an`account' because some unix systems implement strict quotas for computer resources which have to be paid for with realmoney<A NAME="DOCF2" HREF="unix_foot.html#FOOT2">(2)</A>.</P><PRE>  login: mark  password:</PRE><P>Once you have typed in your password, you are `logged on'. Whathappens then depends on what kind of system you are logged ontoand how. If you have a colour monitor and keyboard in front of you,with a graphical user interface, you will see a number ofwindows appear, perhaps a menu bar. You then use a mouse andkeyboard just like any other system.</P><P>This is not the only way to log onto unix. You can also log inremotely, from another machine, using the Secure Shell <CODE>ssh</CODE> program ( thisreplaces the now antiquated <CODE>telnet</CODE> and <CODE>rlogin</CODE><A NAME="IDX102"></A><A NAME="IDX103"></A>programs). If you use these programs, you will normally only get a textor command line interface (though graphical interfaces can easily be arranged).</P><P>Once you have logged in, a short message will be printed (called Messageof the Day or motd) and you will see the C-shell prompt: the name of thehost you are logged onto followed by a percent sign, e.g.</P><PRE>Linux cube 2.2.19pre13 #2 Mon Feb 26 15:53:31 MET 2001 i686 unknown   This is GNU/Linux - send problems to help@example.org10:44pm  up 8 days, 13:34,  3 users,  load average: 0.08, 0.02, 0.01There are 480 messages in your incoming mailbox.</PRE><P>Remember that every UNIX machine is a separate entity: it is not likelogging onto a PC system where you log onto the `network' i.e. the PCfile server. Every UNIX machine is a server, or a client -- more correctlya "peer" (equal partner). The network, in unix-land,has lots of players.<A NAME="IDX104"></A></P><P>The first thing you should do once you have logged on is to set areliable password. A poor password might be okay on a PC which is notattached to a large network, but once you are attached to the Internet,you have to remember that the whole world will be trying to crack yourpassword. Don't think that no one will bother: some people really havenothing better to do.  A password should not contain any word that couldbe in a list of words (in any language), or be a simple concatenation ofa word and a number (e.g. mark123).  It takes seconds to crack such apassword. Choose instead something which is easy to remember. Feel freeto use the PIN number from your bankers card in your password! This willleave you with fewer things to remember. e.g. Ma9876rk). Passwords canbe up to eight characters long.</P><P>Some sites allow you to change your passwordanywhere. Other sites require you to log onto a special machine tochange your password:</P><PRE> dax%  dax% passwd Change your password on host nexus You cannot change it here dax% rlogin nexus password: ****** nexus% passwd Changing password for mark Enter login password: ******** Enter new password: ******** Reenter new passwd: ********</PRE><P>You will be prompted for your old password and your newpassword twice. If your network is large, it might take the system up toan hour or two to register the change in your password, so don't forgetthe old one right away!</P><H2><A NAME="SEC20" HREF="unix_toc.html#TOC20">Mouse buttons</A></H2><P>UNIX has three mouse buttons. On some PC's running GNU/Linux or some otherPC unix, there are only two, but the middle mouse button can besimulated by pressing both mouse buttons simultaneously.  The mousebuttons have the following general functions. They may also have additionalfunctions in special software.<DL COMPACT><DT><EM>index finger</EM><DD>This is used to select and click on objects.It is also used to mark out areas and copy by dragging.This is the button you normally use. <DT><EM>middle finger</EM><DD>Used to pull down menus. It is also used to paste a markedarea somewhere at the mouse position.<DT><EM>outer finger</EM><DD>Pulls down menus.</DL><P>On a left-handed system right and left are reversed.</P><H2><A NAME="SEC21" HREF="unix_toc.html#TOC21">E-mail</A></H2><P>Reading electronic mail on unix is just like any other system, but thereare many programs to choose from. There are very old programs from theseventies such as</P><PRE>mail</PRE><P>and there are fully graphical mail programs such as<PRE>tkratmailtool</PRE><P>Choose the program you like best. Not all of the programs support modernmultimedia extensions because of their age. Some programs like<CODE>tkrat</CODE> have immediate mail notification alerts. To start a mailprogram you just type its name. If you have an icon-bar, you can clickon the mail-icon.</P><H2><A NAME="SEC22" HREF="unix_toc.html#TOC22">Simple commands</A></H2><P>Inexperienced computer users often prefer to use file-managerprograms to avoid typing anything. With a mouse you can clickyour way through directories and files without having to typeanything (e.g. the <CODE>kfm</CODE> or <CODE>tkdesk</CODE> programs).More experienced users generally find this to be slow andtedious after a while and prefer to use written commands. UNIX has many short cuts and keyboard features which maketyped commands extremely fast and much more powerful thanuse of the mouse.</P><P>Today the CDE, KDE and GNOME projects are the most importantefforts to write graphical user interfaces for computers. The CDE(Common Desktop Environment) is a commercial program developedby IBM, Hewlett-Packard, Sun Microsystems and many other vendors.KDE (a German effort, a pun on CDE) and GNOME are free softwarewindow systems which have taken windowing to the next level.While they have borrowed and stolen many ideas from Windows'innovative Windows 95 user interface, they have taken windowingbeyond this.</P><P>If you come from a Windows environment, the UNIX commands can bea little strange. It is a different way of thinking: using language toask for exactly what you want, instead of pointing to a menu of limitedchoices.  It is also a strange language.  Because they stem from an erawhen keyboards had to be hit with hammer force, and machines were veryslow, the UNIX command names are as short as possible, so they seempretty cryptic. Some familiar ones which DOS borrowed from UNIX include,</P><PRE>cdmkdir</PRE><P>which change to a new directory and make a new directory respectively.To list the files in the current directory you use,<PRE>ls</PRE><P>To rename a file, you `move' it:<PRE>mv <VAR>old-name</VAR> <VAR>new-name</VAR></PRE><H2><A NAME="SEC23" HREF="unix_toc.html#TOC23">Text editing and word processing</A></H2><P>Text editing is one of the things which people spend mosttime doing on any computer. It is important to distinguishtext editing from word processing. On a PC or MacIntosh, you areperhaps used to Word or WordPerfect for writing documents.</P><P>UNIX has a Word-like program called <CODE>lyx</CODE>, and even severalOffice clones (e.g. Star Office <CODE>soffice</CODE>), but for the most partUNIX users do not use word processors. It is more common in the UNIXcommunity to write all documents, regardless of whether they areletters, books or computer programs, using a non-formatting texteditor. (UNIX word processors like <CODE>Framemaker</CODE> do exist, but theyare very expensive. A version of MS-Word also exists for some unices.)Once you have written a document in a normal text editor, you call upa text formatter to make it pretty. You might think this strange, butthe truth of the matter is that this two-stage process gives you themost power and flexibility--and that is what most UNIX folks like.</P><P>For writing programs, or anything else, you edit a file by typing:<PRE> emacs myfile</PRE><P><CODE>emacs</CODE> is one of dozens of text-editors. It is not the simplest ormost intuitive, but it is the most powerful and if you are going tospend time learning an editor, it wouldn't do any harm to make it thisone.  You could also click on emacs' icon if you are relying on a windowsystem.  Emacs is almost certainly the most powerful text editor thatexists on any system. It is not a word-processor, it is not for formattingprinted documents, but it can be linked to almost any other program inorder to format and print text. It contains a powerful programminglanguage and has many intelligent features.  We shall not go into thedetails of document formatting in this book, but only mention thatprograms like <CODE>troff</CODE> and <CODE>Tex</CODE> or <CODE>Latex</CODE> are used forthis purpose to obtain typeset-quality printing. Text formatting is anarea where UNIX folks do things differently to PC folks.</P><H1><A NAME="SEC24" HREF="unix_toc.html#TOC24">The login environment</A></H1><P><A NAME="IDX105"></A><A NAME="IDX106"></A><A NAME="IDX107"></A></P><P>UNIX began as a timesharing mainframe system in the seventies, when theonly terminals available were text based <EM>teletype</EM> terminals or<EM>tty</EM>-s.  Later, the Massachusetts Institute of Technology (MIT)developed the X-windows interface which is now a standard across UNIXplatforms. Because of this history, the X-window system works as afront end to the standard UNIX shell and interface, so to understandthe user environment we must first understand the shell.<A NAME="IDX108"></A></P><H2><A NAME="SEC25" HREF="unix_toc.html#TOC25">Shells</A></H2><P><A NAME="IDX109"></A>A shell is a command interpreter. In the early days of UNIX, a shell wasthe only way of issuing commands to the system. Nowadays many window-basedapplication programs provide menus and buttons to perform simple commands,but the UNIX shell remains the most powerful and flexible way of interactingwith the system.</P><P><A NAME="IDX110"></A>After logging in and entering a password, the UNIX process <EM>init</EM>starts a shell for the user logging in. UNIX has several different kindsof shell to choose from, so that each user can pick his/her favouritecommand interface. The type of shell which the system starts at login isdetermined by the user's entry in the <EM>passwd</EM> database.On most systems, the standard login shell is a variant of the C-shell.</P><P>Shells provide facilities and commands which</P><UL><LI>Start and stop processes (programs)<LI>Allow two processes to communicate through a <EM>pipe</EM><LI>Allow the user to redirect the flow of input or output<LI>Allow simple command line editing and command history<LI>Define aliases to frequently used commands<LI>Define global "environment" variables which are used to configurethe default behaviour of a variety of programs. These lie in an"associated array" for each process and may be seen with the<SAMP>`env'</SAMP> command. Environment variables are inherited by allprocesses which are started from a shell.<A NAME="IDX111"></A><LI>Provide wildcard expansion (joker notation) of filenames using <SAMP>`*,?,[]'</SAMP><A NAME="IDX112"></A><LI>Provide a simple script language, with tests and loops, so that userscan combine system programs to create new programs of their own.<LI>Change and remember the location of the current working directory, orlocation within the file hierarchy.</UL><P>The shell does not contain any more specific functions--all other commands, suchas programs which list files or create directories etc., are executableprograms which are independent of the shell.  When you type <SAMP>`ls'</SAMP>,the shell looks for the executable file called <SAMP>`ls'</SAMP> in a speciallist of directories called <EM>the command path</EM> (which is contained in the environment variable $PATH) and attempts to startthis program.  This allows such programs to be developed and replacedindependently of the actual command interpreter.</P><P>Each shell which is started can be customized and configured by editinga setup file. For the Bash shell this file is called<TT>`.bashrc'</TT>, and for the C-shell and its variants it is called<TT>`.profile'</TT>. (Note that files which begin with leading dots are notnormally visible with the <SAMP>`ls'</SAMP> command. Use <SAMP>`ls -a'</SAMP> to view these.)Any commands which are placed in these files are interpreted by the shellbefore the first command prompt is issued. These files are typicallyused to define a command search path and terminal characteristics.</P><P><EM>On each new command line you can use the cursor keys to edit the line.The up-arrow browses back through earlier commands. <KBD>CTRL-a</KBD> takesyou to the start of the line. <KBD>CTRL-e</KBD> takes you to the end of theline. The <KBD>TAB</KBD> can be used to save typing with the `completion'facility See section <A HREF="unix.html#SEC76">Command/filename completion</A>.</EM></P><P> </P><H3><A NAME="SEC26" HREF="unix_toc.html#TOC26">Shell commands generally</A></H3><P>Shell commands are commands like <CODE>cp</CODE>, <CODE>mv</CODE>,<CODE>passwd</CODE>, <CODE>cat</CODE>, <CODE>more</CODE>, <CODE>less</CODE>, <CODE>cc</CODE>,<CODE>grep</CODE>, <CODE>ps</CODE> etc..</P><P>One thing you can always bet on with Unix is that there is notjust one way of doing things -- there are so many standards, thatthere is often a bewildering array to choose from. UNIX has two maincommand shells. They are called <CODE>sh</CODE> (Bourne Shell) and <CODE>csh</CODE> C-shell. Theirmodern implementations are called <CODE>Bash</CODE> (Bourne Again Shell)and <CODE>tcsh</CODE> (T-C shell).</P><P>Very few commands are actually built into the shell command lineinterpreter, in the same way that they are built into DOS. Rathercommands are programs which exist as actual program files. When we typea command, the shell searches for a program with the same name and triesto execute it.  This is very flexible, since anyone is free to writetheir own programs and therefore extend the command language of thesystem.  Thefile must be executable, or a <CODE>Command not found</CODE> error willresult. To see what actually happens when you type a command like<CODE>gcc</CODE>, try typing the following into a GNU/Linux system: (youcan type this exactly as shown into a Bash shell)<PRE>cube$ IFS=:cube$ for dir in $PATH       # for every directory in the list path&#62;do&#62;  if [ -x $dir/gcc ]        # if the file is executable&#62;  then&#62;     echo Found $dir/gcc    # Print message found!&#62;     break                  # break out of loop&#62;  else&#62;     echo Searching $dir/gcc   &#62;  fi&#62;done</PRE><P>If you use C-shell (e.g. tcsh), try typing in the following C-shell commands <EM>directlyinto a C-shell</EM>. </P><PRE>nexus%  foreach dir ( $path )  # for every directory in the list path&#62;    if ( -x $dir/gcc ) then   # if the file is executable&#62;      echo Found $dir/gcc     # Print message found!&#62;      break                   # break out of loop&#62;    else&#62;      echo Searching $dir/gcc &#62;    endif&#62;  end</PRE><P>The output of these command sequences is something like this:</P><PRE>  Searching /usr/lang/gcc  Searching /usr/openwin/bin/gcc  Searching /usr/openwin/bin/xview/gcc  Searching /physics/lib/framemaker/bin/gcc  Searching /physics/motif/bin/gcc  Searching /physics/mutils/bin/gcc  Searching /physics/common/scripts/gcc  Found /physics/bin/gcc</PRE><P>If you type<PRE>  echo $PATH</PRE><P>in Bourne Shell, or<PRE>  echo $path</PRE><P>in C-shellyou will see the entire list of directories which are searched by the shell.If we had left out the `break' command, we might have discovered thatUNIX often has several programs with the same name, in different directories!For example,<PRE>/bin/mail/usr/ucb/mail/bin/Mail/bin/make/usr/local/bin/make.</PRE><P>Also, different versions of UNIX have different conventions for placing thecommands in directories, so the path list needs to be different fordifferent types of UNIX machine. In Bash a few basic commandslike <CODE>cd</CODE> and <CODE>kill</CODE> are built into the shell (as in DOS).</P><P>You can find out which directory a command is stored in using <PRE>type</PRE><P>command. For example<PRE>cube$ type cdcd is a shell builtincube$ type mvmv is /bin/mvcube$ </PRE><P><CODE>type</CODE> only searches the directories in <CODE>$PATH</CODE> and quits afterthe first match, so if there are several commands with the same name,you will only see the first of them using <CODE>type</CODE>.<A NAME="IDX113"></A><A NAME="IDX114"></A></P><P>Finally, in the C-shell the command corresponding to type is built in and called <CODE>which</CODE>. In Bash <CODE>which</CODE> is a program:<PRE>cube$ type whichwhich is /usr/bin/whichcube$ tcshcube% which whichwhich: shell built-in command.</PRE><P>Take a look at the script <CODE>/usr/bin/which</CODE>. It is a script writtenin bash.<A NAME="IDX115"></A><A NAME="IDX116"></A></P><P> <H3><A NAME="SEC27" HREF="unix_toc.html#TOC27">Environment and shell variables</A></H3><P><A NAME="IDX117"></A>Environment variables are variables which the shell keeps. They arenormally used to configure the behaviour of utility programs like<CODE>lpr</CODE> (which sends a file to the printer) and <CODE>mail</CODE> (whichreads and sends mail) so that special options do not have to be typed inevery time you run these programs.</P><P>Any program can read these variables to find out how you haveconfigured your working environment. We shall meet these variablesfrequently. Here are some important variables</P><P><A NAME="IDX118"></A><A NAME="IDX119"></A><A NAME="IDX120"></A><A NAME="IDX121"></A><A NAME="IDX122"></A><A NAME="IDX123"></A><A NAME="IDX124"></A><PRE>PATH             # The search path for shell commands (bash)TERM             # The terminal type (bash and csh)DISPLAY          # X11 - the name of your displayLD_LIBRARY_PATH  # Path to search for object and shared librariesHOSTNAME         # Name of this UNIX hostPRINTER          # Default printer (lpr)HOME             # The path to your home directory (bash)PS1              # The default prompt for bashpath             # The search path for shell commands (csh)term             # The terminal type (csh)prompt           # The default prompt for cshhome             # The path to your home directory (csh)</PRE><P>These variables fall into two groups. Traditionally the first groupalways have names in uppercase letters and are called <EM>environmentvariables</EM>, whereas variables in the second group have names withlowercase letters and are called <EM>shell variables</EM>-- but this isonly a convention. The uppercase variables are <EM>global variables</EM>,whereas the lower case variables are <EM>local variables</EM>. Localvariables are not defined for programs or sub-shells started by thecurrent shell, while global variables are inherited by all sub-shells.<A NAME="IDX125"></A><A NAME="IDX126"></A><A NAME="IDX127"></A><A NAME="IDX128"></A></P><P>The Bash-shell and the C-shell use these conventions differently and notalways consistently.  You will see how to define these below. For nowyou just have to know that you can use the command <CODE>env</CODE> can be usedin Bash shell to see all of the defined global environment variables while <CODE>set</CODE> lists both the global and the local variables.<A NAME="IDX129"></A><A NAME="IDX130"></A></P><P> <H3><A NAME="SEC28" HREF="unix_toc.html#TOC28">Wildcards</A></H3><P><A NAME="IDX131"></A><A NAME="IDX132"></A><A NAME="IDX133"></A><A NAME="IDX134"></A><A NAME="IDX135"></A><A NAME="IDX136"></A></P><P>Sometimes you want to be able to refer to several files in one go. Forinstance, you might want to copy all files ending in `.c' to a newdirectory. To do this one uses <EM>wildcards</EM>. Wildcards are characterslike <CODE>* ?</CODE> which stand for any character or group of characters.In card games the joker is a `wild card' which can be substituted forany other card. Use of wildcards is also called <EM>filename substitution</EM>in the UNIX manuals, in the sections on <CODE>sh</CODE> and <CODE>csh</CODE>.</P><P>The wildcard symbols are,</P><DL COMPACT><DT><SAMP>`?'</SAMP><DD>Match single character. e.g. <CODE>ls /etc/rc.????</CODE><DT><SAMP>`*'</SAMP><DD>Match any number of characters. e.g. <CODE>ls /etc/rc.*</CODE><DT><SAMP>`[...]'</SAMP><DD>Match any character in a list enclosed by these brackets. e.g. <CODE>ls [abc].C</CODE></DL><P>Here are some examples and explanations.</P><DL COMPACT><DT><SAMP>`/etc/rc.????'</SAMP><DD>Match all files in /etc whose first threecharacters are <CODE>rc.</CODE> and are 7 characters long.<DT><SAMP>`*.c'</SAMP><DD>Match all files ending in `.c' i.e. all C programs.<DT><SAMP>`*.[Cc]'</SAMP><DD>List all files ending on `.c' or `.C' i.e. all C and C++ programs.<DT><SAMP>`*.[a-z]'</SAMP><DD>Match any file ending in .a, .b, .c, ... up to .z etc.</DL><P><A NAME="IDX137"></A>It is important to understand that <EM>the shell expands wildcards</EM>. Whenyou type a command, the program is not invoked with an argument thatcontains <CODE>*</CODE> or <CODE>?</CODE>. The shell expands the special charactersfirst and invokes commands with the entire list of files whichmatch the patterns. The programs never see the wildcard characters, onlythe list of files they stand for. To see this in action, you can type<PRE>echo /etc/rc*</PRE><P>which gives<PRE>/etc/rc0 /etc/rc0.d /etc/rc1 /etc/rc1.d /etc/rc2 /etc/rc2.d /etc/rc3 /etc/rc3.d /etc/rc5 /etc/rc6 /etc/rcS /etc/rcS.d</PRE><P>All shell commands are invoked with a command line of this form. Thishas an important corollary. It means that multiple renaming <EM>cannot work</EM>!</P><P>UNIX files are renamed using the <CODE>mv</CODE> command. In many microcomputeroperating systems one can write<PRE>rename *.x *.y</PRE><P>which changes the file extension of all files ending in `.x' to the samename with  a `.y' extension. This cannot work in UNIX, because theshell tries expands everything before passing the arguments to thecommand line.</P><P> <H3><A NAME="SEC29" HREF="unix_toc.html#TOC29">Regular expressions</A></H3><P><A NAME="IDX138"></A><A NAME="IDX139"></A><A NAME="IDX140"></A>The wildcards belong to the shell. They are used for matchingfilenames. UNIX has a more general and widely used mechanism formatching <EM>strings</EM>, this is through <EM>regular expressions</EM>.</P><P>Regular expressions are used by the <CODE>egrep</CODE> utility, text editorslike <CODE>ed</CODE>, <CODE>vi</CODE> and <CODE>emacs</CODE> and <CODE>sed</CODE> and <CODE>awk</CODE>.They are also used in the C programming language for matching input as well as in the Perl programming language and <CODE>lex</CODE>tokenizer. Here are some examples using the <CODE>egrep</CODE> commandwhich print lines from the file <CODE>/etc/rc</CODE> which match certainconditions. The <CODE></CODE> construction is part of <CODE>egrep</CODE>. Everythingin between these symbols is a regular expression. Notice thatspecial shell symbols <CODE>! * &#38;</CODE> have to be preceded with a backslash<CODE>\</CODE> in order to prevent the shell from expanding them!<A NAME="IDX141"></A></P><PRE># Print all lines beginning with a comment #egrep '(^#)'           /etc/rc# Print all lines which DON'T begin with #egrep '(^[^#])'        /etc/rc# Print all lines beginning with e, f or g.egrep '(^[efg])'       /etc/rc # Print all lines beginning with uppercaseegrep '(^[A-Z])'       /etc/rc# Print all lines NOT beginning with uppercaseegrep '(^[^A-Z])'      /etc/rc # Print all lines containing ! * &#38;egrep '([\!\*\&#38;])'     /etc/rc # All lines containing ! * &#38; but not starting #egrep '([^#][\!\*\&#38;])' /etc/rc </PRE><P>Regular expressions are made up of the following `atoms'.</P><P>These examples assume that the file <TT>`/etc/rc'</TT> exists.If it doesn't exist on the machine you are using, try tofind the equivalent by, for instance, replacing<CODE>/etc/rc</CODE> with <CODE>/etc/rc*</CODE> which will try tofind a match beginning with the rc.</P><P><A NAME="IDX142"></A><A NAME="IDX143"></A><A NAME="IDX144"></A><A NAME="IDX145"></A><A NAME="IDX146"></A><A NAME="IDX147"></A><A NAME="IDX148"></A><A NAME="IDX149"></A><A NAME="IDX150"></A><A NAME="IDX151"></A><A NAME="IDX152"></A><A NAME="IDX153"></A><A NAME="IDX154"></A><A NAME="IDX155"></A></P><DL COMPACT><DT><SAMP>`.'</SAMP><DD>Match any single character except the end of line.<DT><SAMP>`^'</SAMP><DD>Match the beginning of a line as the first character.<DT><SAMP>`$'</SAMP><DD>Match end of line as last character.<DT><SAMP>`[..]'</SAMP><DD>Match any character in the list between the square brackets.(see below).<DT><SAMP>`*'</SAMP><DD>Match zero or more occurrences of the preceding expression.<DT><SAMP>`+'</SAMP><DD>Match one or more occurrences of the preceding expression.<DT><SAMP>`?'</SAMP><DD>Match zero or one occurrence of the preceding expression.</DL><P>You can find a complete list in the UNIX manual pages. The squarebrackets above are used to define a <EM>class</EM> of characters to bematched. Here are some examples,</P><UL><LI>If the square brackets contain a list ofcharacters, $[a-z156]$ then a single occurrence of any character in thelist will match the regular expression: in this case any lowercaseletter or the numbers 1, 5 and 6.<LI>If the first character in the brackets is the caretsymbol <SAMP>`^'</SAMP> then any character <EM>except</EM> those in the list willbe matched. <LI>Normally a dash or minus sign <SAMP>`-'</SAMP> means a range of characters.If it is the first character after the <SAMP>`['</SAMP> or after <SAMP>`[^'</SAMP> then itis treated literally.</UL><P> <H3><A NAME="SEC30" HREF="unix_toc.html#TOC30">Nested shell commands and "</A></H3><P><A NAME="IDX156"></A><A NAME="IDX157"></A></P><P>The backwards apostrophes `...` can be used in all shells and also inthe programming language Perl.  When these are encountered in astring the shell tries to execute the command inside the quotes andreplace the quoted expression by the result of that command. For example: <PRE>UNIX$ echo "This system's kernel type is `/usr/bin/file /boot/vmlinuz-2.2.19pre13`"This system's kernel type is /boot/vmlinuz-2.2.19pre13: Linux kernel x86 boot executable bzImage, version 2.2.19pre13 UNIX$ for file in `ls /local/ssl/misc/*` &#62; do &#62; echo I found a config file $file&#62; echo Its type is `/usr/bin/file $file`&#62; doneI found a config file /local/ssl/misc/CA.plIts type is /local/ssl/misc/CA.pl: perl script textI found a config file /local/ssl/misc/CA.shIts type is /local/ssl/misc/CA.sh: Bourne shell script textI found a config file /local/ssl/misc/c_hashIts type is /local/ssl/misc/c_hash: Bourne shell script textI found a config file /local/ssl/misc/c_infoIts type is /local/ssl/misc/c_info: Bourne shell script textI found a config file /local/ssl/misc/c_issuerIts type is /local/ssl/misc/c_issuer: Bourne shell script textI found a config file /local/ssl/misc/c_nameIts type is /local/ssl/misc/c_name: Bourne shell script textI found a config file /local/ssl/misc/der_chopIts type is /local/ssl/misc/der_chop: perl script text</PRE><P>This is how we insert the result of a shell command into a text string orvariable.<A NAME="IDX158"></A><A NAME="IDX159"></A><A NAME="IDX160"></A></P><H2><A NAME="SEC31" HREF="unix_toc.html#TOC31">UNIX command overview</A></H2><H3><A NAME="SEC32" HREF="unix_toc.html#TOC32">Important keys</A></H3><DL COMPACT><DT><KBD>TAB</KBD><DD>The <KBD>TAB</KBD> key is used by Bash and Emacs for "filename completion", i.e.when you are uncertain of the correct name of something, or simplycan't be bothered to type it out, you can hit <KBD>TAB</KBD> to eitherfinish off the word, or show you alternative choices. e.g. try in Bash<PRE>cube$ load<KBD>TAB</KBD>loadkeys    loadmeter   loadunimap  </PRE>This shows the possible completions of commands which match "load".Type one more letter and <KBD>TAB</KBD>, and the rest will be filled in.<DT><KBD>CTRL-A</KBD><DD>Jump to start of line. If <SAMP>`screen'</SAMP> is active, thisprefixes all control key commands for <SAMP>`screen'</SAMP> and thenthe normal <KBD>CTRL-A</KBD> is replaced by <KBD>CTRL-a a</KBD>.<A NAME="IDX161"></A><A NAME="IDX162"></A><DT><KBD>CTRL-C</KBD><DD>Interrupt or break key. Sends signal 15 to a process.<A NAME="IDX163"></A><A NAME="IDX164"></A><DT><KBD>CTRL-D</KBD><DD>Signifies <SAMP>`EOF'</SAMP> (end of file) or shows expansionmatches in command/filename completion See section <A HREF="unix.html#SEC76">Command/filename completion</A>.<A NAME="IDX165"></A><A NAME="IDX166"></A><DT><KBD>CTRL-E</KBD><DD>Jump to end of line.<A NAME="IDX167"></A><A NAME="IDX168"></A><DT><KBD>CTRL-L</KBD><DD>Clear screen in newer shells and in emacs. Same as <SAMP>`clear'</SAMP>in the shell.<A NAME="IDX169"></A><A NAME="IDX170"></A><DT><KBD>CTRL-Z</KBD><DD>Suspend the present process, but do not destroy it. This sendssignal 18 to the process.<A NAME="IDX171"></A><A NAME="IDX172"></A></DL><H3><A NAME="SEC33" HREF="unix_toc.html#TOC33">Alternative shells</A></H3><P><A NAME="IDX173"></A></P><DL COMPACT><DT><CODE>bash</CODE><DD>The Bourne Again shell, an improved sh.<A NAME="IDX174"></A><DT><CODE>csh</CODE><DD>The standard C-shell.<A NAME="IDX175"></A><DT><CODE>jsh</CODE><DD>The same as sh, with C-shell style job control.<A NAME="IDX176"></A><DT><CODE>ksh</CODE><DD>The Korn shell, an improved sh.<A NAME="IDX177"></A><DT><CODE>sh</CODE><DD>The original Bourne shell.<A NAME="IDX178"></A><DT><CODE>sh5</CODE><DD>On ULTRIX systems the standard Bourne shell isquite stupid. sh5 corresponds to the normal Bourne shellon these systems.<A NAME="IDX179"></A><DT><CODE>tcsh</CODE><DD>An improved C-shell.<A NAME="IDX180"></A><DT><CODE>zsh</CODE><DD>An improved sh.<A NAME="IDX181"></A></DL><H3><A NAME="SEC34" HREF="unix_toc.html#TOC34">Window based terminal emulators</A></H3><P><A NAME="IDX182"></A><A NAME="IDX183"></A></P><DL COMPACT><DT><CODE>xterm</CODE><DD>The standard X11 terminal window.<A NAME="IDX184"></A><A NAME="IDX185"></A><DT><CODE>shelltool, cmdtool</CODE><DD>Openwindows terminals from Sun Microsystems. These arenot completely X11 compatible during copy/paste operations.<A NAME="IDX186"></A><A NAME="IDX187"></A><A NAME="IDX188"></A><A NAME="IDX189"></A><DT><CODE>screen</CODE><DD>This is not a window in itself, but allows you to emulatehaving several windows inside a single (say) xterm window.The user can switch between different windows and open newones, but can only see one window at a time See section <A HREF="unix.html#SEC60">Multiple screens</A>.<A NAME="IDX190"></A><A NAME="IDX191"></A></DL><H3><A NAME="SEC35" HREF="unix_toc.html#TOC35">Remote shells and logins</A></H3><P>The best way to log onto another system is to use the Secure Shellcommand <CODE>ssh</CODE>. This replaces the now obsolete commands:</P><DL COMPACT><DT><CODE>rlogin</CODE><DD>Login onto a remote UNIX system.<A NAME="IDX192"></A><A NAME="IDX193"></A><DT><CODE>rsh</CODE><DD>Open a shell on a remote system (require access rights).<A NAME="IDX194"></A><A NAME="IDX195"></A><DT><CODE>telnet</CODE><DD>Open a connection to a remove system using the telnetprotocol.<A NAME="IDX196"></A><A NAME="IDX197"></A></DL><P>These old commands are insecure andnote very flexible.The Secure Shell offers encryption, strong authenticationand greater functionality. It can be used to run a singleprogram on a remote machine, or to login on the remote machine.</P><PRE>cube$ ssh metaverse datecube$ ssh metaverse</PRE><H3><A NAME="SEC36" HREF="unix_toc.html#TOC36">Text editors</A></H3><DL COMPACT><DT><CODE>ed</CODE><DD>An ancient line-editor.<A NAME="IDX198"></A><A NAME="IDX199"></A><DT><CODE>vi</CODE><DD>Visual interface to <CODE>ed</CODE>. This is the only "standard"UNIX text editor supplied by vendors.<A NAME="IDX200"></A><A NAME="IDX201"></A><DT><CODE>emacs</CODE><DD>The most powerful UNIX editor. A fully configurable, userprogrammable editor which works under X11 and on tty-terminals.<A NAME="IDX202"></A><A NAME="IDX203"></A><DT><CODE>xemacs</CODE><DD>A pretty version of emacs for X11 windows.<A NAME="IDX204"></A><A NAME="IDX205"></A><DT><CODE>pico</CODE><DD>A tty-terminal only editor, comes as part of the PINE mailpackage.<A NAME="IDX206"></A><A NAME="IDX207"></A><DT><CODE>xedit</CODE><DD>A test X11-only editor supplied with X-windows.<A NAME="IDX208"></A><A NAME="IDX209"></A><DT><CODE>textedit</CODE><DD>A simple X11-only editor supplied by Sun Microsystems.<A NAME="IDX210"></A><A NAME="IDX211"></A></DL><H3><A NAME="SEC37" HREF="unix_toc.html#TOC37">File handling commands</A></H3><DL COMPACT><DT><CODE>ls</CODE><DD>List files in specified directory (like <CODE>dir</CODE> on othersystems).<A NAME="IDX212"></A><A NAME="IDX213"></A><DT><CODE>cp</CODE><DD>Copy files.<A NAME="IDX214"></A><A NAME="IDX215"></A><DT><CODE>mv</CODE><DD>Move or rename files.<A NAME="IDX216"></A><A NAME="IDX217"></A><A NAME="IDX218"></A><A NAME="IDX219"></A><DT><CODE>touch</CODE><DD>Creates an empty new file if none exists, or updates dateand time stamps on existing files.<A NAME="IDX220"></A><A NAME="IDX221"></A><A NAME="IDX222"></A><A NAME="IDX223"></A><A NAME="IDX224"></A><A NAME="IDX225"></A><DT><CODE>rm, unlink</CODE><DD>Remove a file or link (delete).<A NAME="IDX226"></A><A NAME="IDX227"></A><A NAME="IDX228"></A><A NAME="IDX229"></A><DT><CODE>mkdir, rmdir</CODE><DD>Make or remove a directory. A directory must be empty in orderto be able to remove it.<A NAME="IDX230"></A><A NAME="IDX231"></A><A NAME="IDX232"></A><A NAME="IDX233"></A><A NAME="IDX234"></A><A NAME="IDX235"></A><A NAME="IDX236"></A><DT><CODE>cat</CODE><DD>Concatenate or join together a number of files. The output iswritten to the standard output by default. Can also be usedto simply print a file on screen.<A NAME="IDX237"></A><A NAME="IDX238"></A><DT><CODE>lp, lpr</CODE><DD>Line printer. Send a file to the default printer, or the printerdefined in the <SAMP>`PRINTER'</SAMP> environment variable.<A NAME="IDX239"></A><A NAME="IDX240"></A><A NAME="IDX241"></A><A NAME="IDX242"></A><A NAME="IDX243"></A><A NAME="IDX244"></A><A NAME="IDX245"></A><DT><CODE>lpq, lpstat</CODE><DD>Show the status of the print queue.<A NAME="IDX246"></A><A NAME="IDX247"></A><A NAME="IDX248"></A><A NAME="IDX249"></A><A NAME="IDX250"></A><A NAME="IDX251"></A></DL><H3><A NAME="SEC38" HREF="unix_toc.html#TOC38">File browsing</A></H3><DL COMPACT><DT><CODE>more</CODE><DD>Shows one screen full at a time. Possibility to search fora string and edit the file. This is like <SAMP>`type <VAR>file</VAR> | more'</SAMP> in DOS.<A NAME="IDX252"></A><A NAME="IDX253"></A><A NAME="IDX254"></A><A NAME="IDX255"></A><A NAME="IDX256"></A><DT><CODE>less</CODE><DD>An enhanced version of more.<A NAME="IDX257"></A><A NAME="IDX258"></A><A NAME="IDX259"></A><A NAME="IDX260"></A><DT><CODE>mc</CODE><DD>Midnight commander, a free version of the `Norton Commander'PC utility for UNIX. (Only for non-serious UNIX users...)<DT><CODE>kfm</CODE><DD>A window based file manager with icons and all that nonsense.</DL><H3><A NAME="SEC39" HREF="unix_toc.html#TOC39">Ownership and granting access permission</A></H3><P><A NAME="IDX261"></A><A NAME="IDX262"></A><DL COMPACT><DT><CODE>chmod</CODE><DD>Change file access mode.<A NAME="IDX263"></A><A NAME="IDX264"></A><A NAME="IDX265"></A><A NAME="IDX266"></A><DT><CODE>chown, chgrp</CODE><DD>Change owner and group of a file. The GNU version of <CODE>chown</CODE>allows both these operations to be performed together usingthe syntax <CODE>chown <VAR>owner</VAR>.<VAR>group</VAR> <VAR>file</VAR></CODE>.<A NAME="IDX267"></A><A NAME="IDX268"></A><A NAME="IDX269"></A><A NAME="IDX270"></A><DT><CODE>acl</CODE><DD>On newer Unices, Access control lists allow access to be grantedon a per-user basis rather than by groups.<A NAME="IDX271"></A><A NAME="IDX272"></A><A NAME="IDX273"></A><A NAME="IDX274"></A></DL><H3><A NAME="SEC40" HREF="unix_toc.html#TOC40">Extracting from and rebuilding files</A></H3><DL COMPACT><DT><CODE>cut</CODE><DD>Extract a column in a table<A NAME="IDX275"></A><A NAME="IDX276"></A><DT><CODE>paste</CODE><DD>Merge several files so that each file becomes a column ina table.<A NAME="IDX277"></A><A NAME="IDX278"></A><DT><CODE>sed</CODE><DD>A batch text-editor for searching, replacing and selectingtext without human intervention.<A NAME="IDX279"></A><A NAME="IDX280"></A><DT><CODE>awk</CODE><DD>A prerunner to the Perl language, for extracting and modifyingtextfiles.<A NAME="IDX281"></A><A NAME="IDX282"></A><DT><CODE>rmcr</CODE><DD>Strip carriage return (ASCII 13) characters from a file.Useful for converting DOS files to UNIX.</DL><H3><A NAME="SEC41" HREF="unix_toc.html#TOC41">Locating files</A></H3><DL COMPACT><DT><CODE>find</CODE><DD>Search for files from a specified directory using variouscriteria.<A NAME="IDX283"></A><A NAME="IDX284"></A><DT><CODE>locate</CODE><DD>Fast search in a global file database for files containinga search-string.<A NAME="IDX285"></A><A NAME="IDX286"></A><DT><CODE>whereis</CODE><DD>Look for a command and its documentation on the system.<A NAME="IDX287"></A><A NAME="IDX288"></A></DL><H3><A NAME="SEC42" HREF="unix_toc.html#TOC42">Disk usage.</A></H3><P><A NAME="IDX289"></A></P><DL COMPACT><DT><CODE>du</CODE><DD>Show number of blocks used by a file or files.<A NAME="IDX290"></A><A NAME="IDX291"></A><DT><CODE>df</CODE><DD>Show the state of usage for one or more disk partitions.<A NAME="IDX292"></A><A NAME="IDX293"></A></DL><H3><A NAME="SEC43" HREF="unix_toc.html#TOC43">Show other users logged on</A></H3><DL COMPACT><DT><CODE>users</CODE><DD>Simple list of other users.<A NAME="IDX294"></A><A NAME="IDX295"></A><DT><CODE>finger</CODE><DD>Show who is logged onto this and other systems.<A NAME="IDX296"></A><A NAME="IDX297"></A><DT><CODE>who</CODE><DD>List of users logged into this system.<A NAME="IDX298"></A><A NAME="IDX299"></A><DT><CODE>w</CODE><DD>Long list of who is logged onto this system and what theyare doing.<A NAME="IDX300"></A><A NAME="IDX301"></A></DL><H3><A NAME="SEC44" HREF="unix_toc.html#TOC44">Contacting other users</A></H3><DL COMPACT><DT><CODE>write</CODE><DD>Send a simple message to the named user, end with <KBD>CTRL-D</KBD>.The command <SAMP>`mesg n'</SAMP> switches off messages receipt.<A NAME="IDX302"></A><A NAME="IDX303"></A><A NAME="IDX304"></A><A NAME="IDX305"></A><A NAME="IDX306"></A><A NAME="IDX307"></A><DT><CODE>talk</CODE><DD>Interactive two-way conversation with named user.<A NAME="IDX308"></A><A NAME="IDX309"></A><DT><CODE>irc</CODE><DD>Internet relay chat. A conferencing system for realtimemulti-user conversations, for addicts and losers.<A NAME="IDX310"></A><A NAME="IDX311"></A><A NAME="IDX312"></A></DL><H3><A NAME="SEC45" HREF="unix_toc.html#TOC45">Mail senders/readers</A></H3><P><A NAME="IDX313"></A></P><DL COMPACT><DT><CODE>mail</CODE><DD>The standard (old) mail interface.<DT><CODE>Mail</CODE><DD>Another mail interface.<DT><CODE>elm</CODE><DD>Electronic Mail program. Lots of functionality but poorsupport for multimedia.<A NAME="IDX314"></A><A NAME="IDX315"></A>              <DT><CODE>pine</CODE><DD>Rumours (untrue) are that pine stands for Pine is Not Elm;it actually stands for nothing at all.Improved support for multimedia but veryslow and rather stupid at times. Some of the best features ofelm have been removed!<A NAME="IDX316"></A><A NAME="IDX317"></A><DT><CODE>mailtool</CODE><DD>Sun's openwindows client program.<DT><CODE>rmail</CODE><DD>A mail interface built into the emacs editor.<A NAME="IDX318"></A><A NAME="IDX319"></A><DT><CODE>netscape mail</CODE><DD>A mail interface built into the netscape navigator.<DT><CODE>zmail</CODE><DD>A commercial mail package.<A NAME="IDX320"></A><A NAME="IDX321"></A><DT><CODE>tkrat</CODE><DD>A graphical mail reader which supports most MIME types, writtenin tcl/tk. This program has a nice feel and allows you to createa searchable database of old mail messages, but has a hopelesslocking mechanism.</DL><H3><A NAME="SEC46" HREF="unix_toc.html#TOC46">File transfer</A></H3><P><A NAME="IDX322"></A></P><DL COMPACT><DT><CODE>ftp</CODE><DD>The File Transfer program - copies files to/from a remote host.<A NAME="IDX323"></A><A NAME="IDX324"></A><DT><CODE>ncftp</CODE><DD>An enhanced ftp for anonymous login.<A NAME="IDX325"></A><A NAME="IDX326"></A></DL><H3><A NAME="SEC47" HREF="unix_toc.html#TOC47">Compilers</A></H3><P><A NAME="IDX327"></A></P><DL COMPACT><DT><CODE>cc</CODE><DD>The C compiler.<A NAME="IDX328"></A><A NAME="IDX329"></A><DT><CODE>CC</CODE><DD>The C++ compiler.<A NAME="IDX330"></A><A NAME="IDX331"></A><DT><CODE>gcc</CODE><DD>The GNU C compiler.<A NAME="IDX332"></A><A NAME="IDX333"></A><DT><CODE>g++</CODE><DD>The GNU C++ compiler.<A NAME="IDX334"></A><A NAME="IDX335"></A><DT><CODE>javac</CODE><DD>A generator of Java bytecode.<A NAME="IDX336"></A><A NAME="IDX337"></A><DT><CODE>java</CODE><DD>A Java Virtual Machine.<A NAME="IDX338"></A><A NAME="IDX339"></A><DT><CODE>ld</CODE><DD>The system linker/loader.<A NAME="IDX340"></A><A NAME="IDX341"></A><DT><CODE>ar</CODE><DD>Archive library builder.<A NAME="IDX342"></A><A NAME="IDX343"></A><DT><CODE>dbx</CODE><DD>A symbolic debugger.<A NAME="IDX344"></A><A NAME="IDX345"></A><A NAME="IDX346"></A><DT><CODE>gdb</CODE><DD>The GNU symbolic debugger.<A NAME="IDX347"></A><A NAME="IDX348"></A><DT><CODE>xxgdb</CODE><DD>The GNU debugger with a window driven front-end.<DT><CODE>ddd</CODE><DD>A motif based front-end to the gdb debugger.<A NAME="IDX349"></A></DL><P><A NAME="IDX350"></A><A NAME="IDX351"></A><A NAME="IDX352"></A></P><H3><A NAME="SEC48" HREF="unix_toc.html#TOC48">Other interpreted languages</A></H3><DL COMPACT><DT><CODE>perl</CODE><DD>Practical extraction an report language.<DT><CODE>tcl</CODE><DD>A perl-like language with special support for building user interfaces and command shells.<A NAME="IDX353"></A><A NAME="IDX354"></A><DT><CODE>php</CODE><DD>Personal Home Page Tools (officially "PHP: Hypertext Preprocessor"). A server-side HTML-embedded scripting language.<A NAME="IDX355"></A><A NAME="IDX356"></A><DT><CODE>scheme</CODE><DD>A lisp-like extensible scripting language from GNU.<A NAME="IDX357"></A><DT><CODE>mercury</CODE><DD>A prolog-like language for artificial intelligence.<A NAME="IDX358"></A></DL><H3><A NAME="SEC49" HREF="unix_toc.html#TOC49">Processes and system statistics</A></H3><DL COMPACT><DT><CODE>ps</CODE><DD>List system process table.<A NAME="IDX359"></A><A NAME="IDX360"></A><DT><CODE>vmstat</CODE><DD>List kernel virtual-memory statistics.<A NAME="IDX361"></A><A NAME="IDX362"></A><DT><CODE>netstat</CODE><DD>List network connections and statistics.<A NAME="IDX363"></A><A NAME="IDX364"></A><DT><CODE>rpcinfo</CODE><DD>Show rpc information.<A NAME="IDX365"></A><A NAME="IDX366"></A><DT><CODE>showmount</CODE><DD>Show clients mounting local filesystems.<A NAME="IDX367"></A><A NAME="IDX368"></A><A NAME="IDX369"></A></DL><H3><A NAME="SEC50" HREF="unix_toc.html#TOC50">System identity</A></H3><DL COMPACT><DT><CODE>uname</CODE><DD>Display system name and operating system release.<A NAME="IDX370"></A><A NAME="IDX371"></A><A NAME="IDX372"></A><A NAME="IDX373"></A><DT><CODE>hostname</CODE><DD>Show the name of this host.<A NAME="IDX374"></A><A NAME="IDX375"></A><DT><CODE>domainname</CODE><DD>Show the name of the local NIS domain. Normally this ischosen to be the same as the BIND/DNS domain, but itneed not be.<A NAME="IDX376"></A><A NAME="IDX377"></A><A NAME="IDX378"></A><DT><CODE>nslookup</CODE><DD>Interrogate the DNS/BIND name service (hostname to IP addressconversion).<A NAME="IDX379"></A><A NAME="IDX380"></A></DL><P> </P><H3><A NAME="SEC51" HREF="unix_toc.html#TOC51">Internet resources</A></H3><P><A NAME="IDX381"></A><DL COMPACT>   <DT><CODE>archie, xarchie</CODE><DD>Search the internet ftp database for files.<A NAME="IDX382"></A><A NAME="IDX383"></A><A NAME="IDX384"></A><A NAME="IDX385"></A><A NAME="IDX386"></A><A NAME="IDX387"></A><DT><CODE>xrn, fnews</CODE><DD>Read news (browser).<A NAME="IDX388"></A><A NAME="IDX389"></A><A NAME="IDX390"></A><A NAME="IDX391"></A><DT><CODE>netscape, xmosaic</CODE><DD>Read world wide web (WWW) (browser).<A NAME="IDX392"></A><A NAME="IDX393"></A></DL><H3><A NAME="SEC52" HREF="unix_toc.html#TOC52">Text formatting and postscript</A></H3><P><A NAME="IDX394"></A><A NAME="IDX395"></A><DL COMPACT><DT><CODE>tex, latex</CODE><DD>Donald Knuth's text formatting language, pronounced "tek"(the x is really a Greek "chi"). Used widelyfor technical publications. Compiles to dvi (device independent)file format.<A NAME="IDX396"></A><A NAME="IDX397"></A><A NAME="IDX398"></A><A NAME="IDX399"></A><DT><CODE>texinfo</CODE><DD>A hypertext documentation system using tex and "info"format. This is the GNU documentation system.This UNIX guide is written in texinfo!!!<A NAME="IDX400"></A><A NAME="IDX401"></A><A NAME="IDX402"></A><DT><CODE>xdvi</CODE><DD>View a tex dvi file on screen.<A NAME="IDX403"></A><DT><CODE>dvips</CODE><DD>Convert dvi format into postscript.<A NAME="IDX404"></A><A NAME="IDX405"></A><DT><CODE>ghostview, ghostscript</CODE><DD>View a postscript file on screen.<A NAME="IDX406"></A><A NAME="IDX407"></A><A NAME="IDX408"></A><A NAME="IDX409"></A></DL><H3><A NAME="SEC53" HREF="unix_toc.html#TOC53">Picture editors and processors</A></H3><P><A NAME="IDX410"></A></P><DL COMPACT><DT><CODE>xv</CODE><DD>Handles, edits and processes pictures in a variety ofstandard graphics formats (gif, jpg, tiff etc).Use <CODE>xv -quit</CODE> to place a picture on your root window.<A NAME="IDX411"></A><A NAME="IDX412"></A><A NAME="IDX413"></A><A NAME="IDX414"></A><A NAME="IDX415"></A><DT><CODE>xpaint</CODE><DD>A simple paint program.<A NAME="IDX416"></A><A NAME="IDX417"></A><A NAME="IDX418"></A><DT><CODE>xfig</CODE><DD>A line drawing figure editor. Produces postscript, tex,and a variety of other output formats.<A NAME="IDX419"></A><A NAME="IDX420"></A><A NAME="IDX421"></A><DT><CODE>xmgr</CODE><DD>A graphing and analysis program.<A NAME="IDX422"></A><A NAME="IDX423"></A><A NAME="IDX424"></A><DT><CODE>xsetroot</CODE><DD>Load an X-bitmap image into the screen (root window)background. Small images are tiled.<A NAME="IDX425"></A><A NAME="IDX426"></A></DL><H3><A NAME="SEC54" HREF="unix_toc.html#TOC54">Miscellaneous</A></H3><DL COMPACT><DT><CODE>date</CODE><DD>Print the date and time.<A NAME="IDX427"></A><A NAME="IDX428"></A><A NAME="IDX429"></A><DT><CODE>ispell</CODE><DD>Spelling checker.<A NAME="IDX430"></A><A NAME="IDX431"></A><DT><CODE>xcalc</CODE><DD>A graphical calculator.<A NAME="IDX432"></A><A NAME="IDX433"></A><DT><CODE>dc,bc</CODE><DD>Text-based calculators.<A NAME="IDX434"></A><A NAME="IDX435"></A><DT><CODE>xclock</CODE><DD>A clock!<DT><CODE>ping</CODE><DD>Send a "sonar" ping to see if another UNIX host is alive.<A NAME="IDX436"></A><A NAME="IDX437"></A><A NAME="IDX438"></A></DL><H2><A NAME="SEC55" HREF="unix_toc.html#TOC55">Terminals</A></H2><P><A NAME="IDX439"></A><A NAME="IDX440"></A><A NAME="IDX441"></A>In order to communicate with a user, a shell needs to have access to aterminal. UNIX was designed to work with many different kinds ofterminals.  Input/output commands in UNIX read and write to a virtualterminal. In <EM>reality</EM> a terminal might be a text-based Teletypeterminal (called a <EM>tty</EM> for short) or a graphics based terminal;it might be 80-characters wide or it might be wider or narrower. UNIXtake into account these possibility by defining a number of instances ofterminals in a more or less object oriented way.</P><P>Each user's terminal has to be configured before cursor based input/outputwill work correctly. Normally this is done by choosing one of a number ofstandard terminal types a list which is supplied by the system. In practicethe user defines the value of the environment variable <SAMP>`TERM'</SAMP> toan appropriate name. Typical examples are <SAMP>`vt100'</SAMP> and <SAMP>`xterm'</SAMP>.If no standard setup is found, the terminal can always be configuredmanually using UNIX's most cryptic and opaque of commands: <SAMP>`stty'</SAMP>.</P><P>The job of configuring terminals is much easier now that hardware is morestandard. Users' terminals are usually configured centrally by the systemadministrator and it is seldom indeed that one ever has to choose anythingother than <SAMP>`vt100'</SAMP> or <SAMP>`xterm'</SAMP>.</P><H2><A NAME="SEC56" HREF="unix_toc.html#TOC56">The X window system</A></H2><P>Because UNIX originated before windowing technology was available, theuser-interface was not designed with windowing in mind. The X windowsystem attempts to be like a virtual machine park, running a differentprogram in each window. Although the programs appear on one screen, theymay in fact be running on UNIX systems anywhere in the world, with onlythe output being local to the user's display.  The standard shellinterface is available by running an X client application called<SAMP>`xterm'</SAMP> which is a graphical front-end to the standard UNIXtextual interface.</P><P><A NAME="IDX442"></A>The <SAMP>`xterm'</SAMP> program provides a virtual terminal using the X windowsgraphical user interface. It works in exactly the same way as a <EM>tty</EM>terminal, except that standard graphical facilities like copy and pasteare available. Moreover, the user has the convenience of being ableto run a different shell in every window. For example, using the <SAMP>`rlogin'</SAMP>command, it is possible to work on the local system in one window, and onanother remote system in another window. The X-window environment allowsone to cut and paste between windows, regardless of which host the shellruns on.</P><P> </P><H3><A NAME="SEC57" HREF="unix_toc.html#TOC57">The components of the X-window system</A></H3><P>The X11 system is based on the client-server model. You might wonder whya window system would be based on a model which was introduced forinterprocess communication, or network communication. The answer is straightforward.<A NAME="IDX443"></A></P><P>The designers of the X window system realized that network communicationwas to be the paradigm of the next generation of computer systems.They wanted to design a system of windows which would enable a user to sitat a terminal in Massachusetts and work on a machine in Tokyo -- andstill be able to get high quality windows displayed on their terminal.The aim of X windows from the beginning is to create a <EM>distributed</EM>window environment.</P><P>When I log onto my friend's Hewlett Packard workstation to use the texteditor (because I don't like the one on my EUNUCHS workstation) I wantit to work correctly on my screen, with my keyboard -- even though myworkstation is manufactured by a different company. I also want thecolours to be right despite the fact that the HP machine uses acompletely different video hardware to my machine. When I press thecurly brace key <CODE>{</CODE>, I want to see a curly brace, and not somehieroglyphic because the HP station uses a different keyboard.</P><P>These are the problems which X tries to address. In a networkenvironment we need a <EM>common window system</EM> which will work on anykind of hardware, and hide the differences between different machines asfar as possible. But it has to be flexible enough to allow us to changeall of the things we don't like -- to choose our own colours, and thekind of window borders we want etc. Other windowing systems (likeMicrosoft windows) ignore these problems and thereby lock the userto a single vendors products and a single operating system. (That, of course,is no accident.)</P><P>The way X solves this problem is to use the client server model. Each programwhich wants to open a window on somebody's compute screen is aclient of the <EM>X window service</EM>. To get something drawn on a user'sscreen, the client asks a server on the host of interest to draw windowsfor it. No client ever draws anything itself -- it asks the server to do iton its behalf. There are several reasons for this:</P><UL><LI>The clients can all talk a common `window language' or <EM>protocol</EM>.We can hide the difference between different kinds of hardware by makingthe <EM>machine-specific</EM> part of drawing graphics entirely a problemof implementing the server on the particular hardware. When a new type of hardware comes along,we just need to modify the server -- none of the clients need to bemodified.<A NAME="IDX444"></A><LI>We can contact different servers and send our output to differenthardware -- thus even though a program is running on a CPU in Tokyo,it can ask the server in Massachusetts to display its window for it.<LI>When more than one window is on a user's display, it eventuallybecomes necessary to move the windows around and then figure outwhich windows are on top of which other windows etc. If all of thedrawing information is kept in a server, it is straightforward towork out this information. If every client drew where it wanted to,it would be impossible to know which window was supposed to beon top of another.<A NAME="IDX445"></A><A NAME="IDX446"></A></UL><P>In X, the window manager is  a different program to the serverwhich does the drawing of graphics -- but the client-server ideastill applies, it just has one more piece to its puzzle.</P><P> <H3><A NAME="SEC58" HREF="unix_toc.html#TOC58">How to set up X windows</A></H3><P>The X windows system is large and complex and not particularly userfriendly. When you log in to the system, X reads two files in your homedirectory which decide which applications will be started what they willlook like. The files are called<A NAME="IDX447"></A><A NAME="IDX448"></A><A NAME="IDX449"></A></P><DL COMPACT><DT><EM>.Xsession</EM><DD>This file is a shell script which starts up a number of applicationsas background processes and exits by calling a window manager. Hereis a simple example file<PRE>#!/bin/bash## .xsession file##PATH="/usr/bin:/bin:/local/gnu/bin:/usr/X11R6/bin"## List applications here, with &#38; at the end# so they run in the background#  xterm -T NewTitle -sl 1000 -geometry 90x45+16+150 -sb &#38;  xclock &#38;  xbiff -geometry 80x80+510+0 &#38;  netscape -iconic&#38; # Start a window manager. Exec replaces this script with# the fvwm process, so that it doesn't exist as a separate# (useless) process.  exec /local/bin/fvwm</PRE><DT><EM>.Xdefaults</EM><DD>This file specifies all of the resources which X programs use. It can beused to change the colours used by applications, or font types etc. The subjectof X-resources is a large one and we don't have time for it here. Hereis a simple example, which shows how you can make your over-bright xtermand emacs windows less bright grey shade.<PRE>xterm*background: LightGreyEmacs*background: grey92Xemacs*background: grey92</PRE></DL><P> <H3><A NAME="SEC59" HREF="unix_toc.html#TOC59">X displays and authority</A></H3><P>In the terminology used by X11, every client program has to contact a<EM>display</EM> in order to open a window.  A display is a virtual screenwhich is created by the X server on a particular host. X can createseveral separate displays on a given host, though most machines only have one.<A NAME="IDX450"></A><A NAME="IDX451"></A></P><P>When an X client program wants to open a window, it looks in the UNIXenvironment variable <SAMP>`DISPLAY'</SAMP> for the IP address of a hostwhich has an X server it can contact. For example, if we wrote<PRE>DISPLAY="myhost:0"export DISPLAY</PRE><P>the client would try to contact the X server on `myhost' and ask fora window on display number zero (the usual display). If we wrote<PRE>DISPLAY="198.112.208.35:0"export DISPLAY</PRE><P>the client would try to open display zero on the X server at the host with the IPaddress <SAMP>`198.112.208.35'</SAMP>.</P><P>Clearly there must be some kind of security mechanism to prevent justanybody from opening windows on someone's display. X has two suchmechanisms:<A NAME="IDX452"></A><A NAME="IDX453"></A></P><DL COMPACT><DT><EM>xhost</EM><DD><A NAME="IDX454"></A> This mechanism is now obsolete. The <SAMP>`xhost'</SAMP> command is used to definea list of hosts which are allowed to open windows on the user's display.It cannot distinguish between individual users. i.e. the command<CODE>xhost yourhost</CODE> would allow <EM>anyone</EM> using yourhost toaccess the local display. This mechanism is only present for backwardcompatibility with early versions of X windows. Normally one shoulduse the command <CODE>xhost -</CODE> to exclude all others from accessing thedisplay.<DT><EM>Xauthority</EM><DD><A NAME="IDX455"></A><A NAME="IDX456"></A>The Xauthority mechanism has replaced the xhost scheme. It providesa security mechanism which can distinguish individual users, not just hosts.In order for a user to open a window on a display, he/she must havea ticket--called a "magic cookie". This is a binary file called <TT>`.Xauthority'</TT> which is created in the user's home directorywhen he/she first starts the X-windows system. Anyone who doesnot have a recent copy of this file cannot open windows or read thedisplay of the user's terminal. This mechanism is based on the ideathat the user's home directory is available via NFS on all hosts he/shewill log onto, and thus the owner of the display will always have accessto the magic cookie, and will therefore always be able to open windowson the display. Other users must obtain a copy of the file in orderto open windows there. The command <CODE>xauth</CODE> is aninteractive utility used for controlling the contents of the <TT>`.Xauthority'</TT>file. See the <SAMP>`xauth'</SAMP> manual page for more information.</DL><H2><A NAME="SEC60" HREF="unix_toc.html#TOC60">Multiple screens</A></H2><P>The window paradigm has been very successful in many ways, but anyonewho has used a window system knows that the screen is simply not bigenough for all the windows one would like! UNIX has several solutions tothis problem.<A NAME="IDX457"></A><A NAME="IDX458"></A></P><P>One solution is to attach several physical screens to a terminal.The X window system can support any number of physical screens ofdifferent types. A graphical designer might want a high resolutioncolour screen for drawing and a black and white screen for writingtext, for instance. The disadvantage with this method is the costof the hardware.</P><P>A cheaper solution is to use a window manager such as <SAMP>`fwvm'</SAMP> whichcreates a virtual screen of unlimited size on a single monitor. As themouse pointer reaches the edge of the true screen, the window managerreplaces the display with a new "blank screen" in which to placewindows. A miniaturized image of the windows on a control panel acts asa map which makes it possible to find the applications on the virtualscreen.</P><P>Yet another possibility is to create virtual displays inside a singlewindow. In other words, one can collapse several shell windows into asingle <SAMP>`xterm'</SAMP> window by running the program <SAMP>`screen'</SAMP>.  Thescreen command allows you to start several shells in a single window(using <KBD>CTRL-a CTRL-c</KBD>) and to switch between them (by typing<KBD>CTRL-a CTRL-n</KBD>). It is only possible to see one shell window at atime, but it is still possible to cut and paste between windows and onehas a considerable saving of space.  The <SAMP>`screen'</SAMP> command alsoallows you to suspend a shell session, log out, log in again later andresume the session precisely where you left off.</P><P>Here is a summary of some useful screen commands:</P><DL COMPACT><DT><KBD>screen</KBD><DD>Start the screen server.<DT><KBD>screen -r</KBD><DD>Resume a previously suspended screen session if possible.<DT><KBD>CTRL-a CTRL-c</KBD><DD>Start a new shell on top of the others (a fresh `screen') in thecurrent window.<DT><KBD>CTRL-a CTRL-n</KBD><DD>Switch to the next `screen'.<DT><KBD>CTRL-a CTRL-a</KBD><DD>Switch to the last screen used.<DT><KBD>CTRL-a a</KBD><DD>When screen is running, <KBD>CTRL-a</KBD> is used for screen commands andcannot therefore be used in its usual shell meaning of `jump to startof line'. <KBD>CTRL-a a</KBD> replaces this.<DT><KBD>CTRL-a CTRL-d</KBD><DD>Detach the screen session from the current window so that itcan be resumed later. It can be resumedwith the <SAMP>`screen -r'</SAMP> command.<DT><KBD>CTRL-a ?</KBD><DD>Help screen.</DL><H1><A NAME="SEC61" HREF="unix_toc.html#TOC61">Files and access</A></H1><P>To prevent all users from being able to access all files on the system, UNIXrecords information about <EM>who</EM> creates files and also who is allowedto access them later.</P><P><A NAME="IDX459"></A><A NAME="IDX460"></A><A NAME="IDX461"></A><A NAME="IDX462"></A>Each user has a unique <EM>username</EM> or <EM>loginname</EM> together witha unique <EM>user id</EM> or <EM>uid</EM>. The user id is a number, whereas the loginname is a text string -- otherwise the two express the same information.A file belongs to user A if it is <EM>owned</EM> by user A. User A thendecides whether or not other users can read, write or execute thefile by setting the <EM>protection bits</EM> or the <EM>permission</EM> of thefile using the command <CODE>chmod</CODE>.</P><P><A NAME="IDX463"></A><A NAME="IDX464"></A>In addition to user identities, there are groups of users. The idea ofa group is that several named users might want to be able to readand work on a file, without other users being able to access it.Every user is a member of at least one group, called the <EM>logingroup</EM> and each group has both a textual name and a number (<EM>group id</EM>). The <EM>uid</EM> and <EM>gid</EM> of each user is recorded in thefile <CODE>/etc/passwd</CODE> (See chapter 6). Membership of other groupsis recorded in the file <CODE>/etc/group</CODE> or on some systems <CODE>/etc/logingroup</CODE>.</P><H2><A NAME="SEC62" HREF="unix_toc.html#TOC62">Protection bits</A></H2><P><A NAME="IDX465"></A><A NAME="IDX466"></A><A NAME="IDX467"></A><A NAME="IDX468"></A><A NAME="IDX469"></A>The following output is fromthe command <CODE>ls -lag</CODE> executed on a SunOS type machine.<PRE>lrwxrwxrwx  1 root     wheel           7 Jun  1  1993 bin -&#62; usr/bin-r--r--r--  1 root     bin        103512 Jun  1  1993 bootdrwxr-sr-x  2 bin      staff       11264 May 11 17:00 devdrwxr-sr-x 10 bin      staff        2560 Jul  8 02:06 etcdrwxr-sr-x  8 root     wheel         512 Jun  1  1993 exportdrwx------  2 root     daemon        512 Sep 26  1993 home-rwxr-xr-x  1 root     wheel      249079 Jun  1  1993 kadblrwxrwxrwx  1 root     wheel           7 Jun  1  1993 lib -&#62; usr/libdrwxr-xr-x  2 root     wheel        8192 Jun  1  1993 lost+founddrwxr-sr-x  2 bin      staff         512 Jul 23  1992 mntdr-xr-xr-x  1 root     wheel         512 May 11 17:00 netdrwxr-sr-x  2 root     wheel         512 Jun  1  1993 pcfsdrwxr-sr-x  2 bin      staff         512 Jun  1  1993 sbinlrwxrwxrwx  1 root     wheel          13 Jun  1  1993 sys-&#62;kvm/sysdrwxrwxrwx  6 root     wheel         732 Jul  8 19:23 tmpdrwxr-xr-x 27 root     wheel        1024 Jun 14  1993 usrdrwxr-sr-x 10 bin      staff         512 Jul 23  1992 var-rwxr-xr-x  1 root     daemon    2182656 Jun  4  1993 vmUNIX</PRE><P>The first column is a textual representation of the protection bits foreach file. Column two is the number of hard links to the file (See exercisesbelow). The third and fourth columns are the user name and group nameand the remainder show the file size in bytes and the creation date.Notice that the directories <CODE>/bin</CODE> and <CODE>/sys</CODE> aresymbolic links to other directories.</P><P>There are sixteen protection bits for a UNIX file, but onlytwelve of them can be changed by users. These twelve are split into four groupsof three. Each three-bit number corresponds to one <EM>octal</EM> number.</P><P>The leading four invisible bits gives information about the type of file: isthe file a <EM>plain file</EM>, a <EM>directory</EM> or a <EM>link</EM>. In theoutput from <CODE>ls</CODE> this is represented by a single character:<CODE>-</CODE>, <CODE>d</CODE> or <CODE>l</CODE>. </P><P>The next three bits set theso-called <EM>s-bits</EM> and <EM>t-bit</EM> which are explained below.</P><P>The remaining three groups of three bits set flags which indicatewhether a file can be read <SAMP>`r'</SAMP>, written to <SAMP>`w'</SAMP> or executed<SAMP>`x'</SAMP> by (i) the user who created them, (ii) the other users who arein the group the file is marked with, and (iii) any user at all.</P><P><A NAME="IDX470"></A><A NAME="IDX471"></A></P><P>For example, the permission</P><PRE>Type Owner Group Anyone  d  rwx   r-x   ---</PRE><P>tells us that the file is a directory, which can be read and writtento by the owner, can be read by others in its group, but not byanyone else.</P><P><EM>Note about directories.  It is impossible to <CODE>cd</CODE> to adirectory unless the <CODE>x</CODE> bit is set. That is, directories must be`executable' in order to be accessible.</EM></P><P>Here are some examples of the relationship between binary, octaland the textual representation of file modes.<A NAME="IDX472"></A></P><PRE>Binary  Octal   Text 001      1       x  010      2       w  100      4       r  110      6      rw- 101      5      r-x    -      644   rw-r--r--</PRE><P>It is well worth becoming familiar with the octal number representationof these permissions.</P><H2><A NAME="SEC63" HREF="unix_toc.html#TOC63">chmod</A></H2><P><A NAME="IDX473"></A>The <CODE>chmod</CODE> command changes the permission or <EM>mode</EM> of a file. Onlythe owner of the file or the superuser can change the permission.Here are some examples of its use. Try them.</P><PRE># make read/write-able for everyonechmod a+w myfile    # add the 'execute' flag for directory chmod u+x mydir/   # open all files for everyone chmod 755 *        # set the s-bit on my-dir's groupchmod g+s mydir/    # descend recursively into directory opening all fileschmod -R a+r dir    </PRE><H2><A NAME="SEC64" HREF="unix_toc.html#TOC64">Umask</A></H2><P><A NAME="IDX474"></A><A NAME="IDX475"></A><A NAME="IDX476"></A><A NAME="IDX477"></A></P><P>When a new file gets created, the operating system must decide what default protection bits to set on that file. The variable <CODE>umask</CODE> decides this.<CODE>umask</CODE> is normally set by each user in his or her <CODE>.cshrc</CODE>file (see next chapter). For example<PRE>umask 077    # safeumask 022    # liberal</PRE><P>According the UNIX documentation, the value of <CODE>umask</CODE> is<SAMP>`XOR'</SAMP>ed (exclusive <SAMP>`OR'</SAMP>) with a value of <CODE>666 &#38; umask</CODE>for plain files or <CODE>777 &#38; umask</CODE> for directories in order to findout the standard protection. Actually this is not quite true: <SAMP>`umask'</SAMP>only removes bits, it never sets bits which were not already setin <CODE>666</CODE>. For instance</P><P><A NAME="IDX478"></A><PRE>umask               Permission 077                 600 (plain)077                 700 (dir)  022                 644 (plain)022                 755 (dir)  </PRE><P>The correct rule for computing permissions is not XOR but <SAMP>`NOT AND'</SAMP>.</P><P> </P><H3><A NAME="SEC65" HREF="unix_toc.html#TOC65">Making programs executable</A></H3><P><A NAME="IDX479"></A><A NAME="IDX480"></A></P><P>A UNIX program is normally executed by typing its pathname. If the <CODE>x</CODE> execute bit is not set on the file, this will generatea `Permission denied' error. This protects the system frominterpreting nonsense files as programs. To make a program executablefor someone, you must therefore ensure that they can executethe file, using a command like</P><PRE>chmod u+x <VAR>filename</VAR></PRE><P>This command would set execute permissions for the owner of the file;<PRE>chmod ug+x <VAR>filename</VAR></PRE><P>would set execute permissions for the owner and for any users in thesame group as the file.  Note that script programs must also be readablein order to be executable, since the shell has the interpret them byreading.</P><H3><A NAME="SEC66" HREF="unix_toc.html#TOC66">chown and chgrp</A></H3><P><A NAME="IDX481"></A><A NAME="IDX482"></A></P><P>These two commands change the ownership and the group ownership of afile. Only the superuser can change the ownership of a file on mostsystems. This is to prevent users from being able to defeat quotamechanisms.  (On some systems, which do not implement quotas, ordinaryusers can give a file away to another user but not get it back again.)The same applies to group ownership.</P><H3><A NAME="SEC67" HREF="unix_toc.html#TOC67">Making a group</A></H3><P>Normally users other than root cannot define their own groups. Thisis a weakness in UNIX from older times which no one seems to be in a hurryto change. </P><H2><A NAME="SEC68" HREF="unix_toc.html#TOC68">s-bit and t-bit (sticky bit)</A></H2><P><A NAME="IDX483"></A><A NAME="IDX484"></A><A NAME="IDX485"></A></P><P>The <CODE>s</CODE> and <CODE>t</CODE> bits have special uses. They are describedas follows.</P><PRE>Octal     Text       Name 4000      chmod u+s  Setuid bit2000      chmod g+s  Setgid bit1000      chmod +t   Sticky bit</PRE><P>The effect of these bits differs for plain files and directories anddiffer between different versions of UNIX. You should check the manualpage <CODE>man sticky</CODE> to find out about your system! The following iscommon behaviour.</P><P>For executable files, the setuid bit tells UNIX that <EM>regardless ofwho runs the program</EM> it should be executed with the permissions andrights of owner of the file. This is often used to allow normal userslimited access to <CODE>root</CODE> privileges. A <EM>setuid-root</EM> programis executed as <CODE>root</CODE> for any user. The setgid bit sets the groupexecution rights of the program in a similar way.</P><P>In BSD UNIX, if the setgid bit is set on a directory then any newfiles created in that directory assume the group ownership of theparent directory and not the logingroup of the user who created thefile. This is standard policy under system 5.</P><P>A directory for which the sticky bit is set restrict the deletion offiles within it. A file or directoryinside a directory with the t-bit set canonly be deleted or renamed by its owner or the superuser. This isuseful for directories like the mail spool area and <CODE>/tmp</CODE>which must be writable to everyone, but should not allow a userto delete another user's files.</P><P>(Ultrix) If an executable file is marked with a sticky bit, it is held in thememory or system swap area. It does not have to be fetched fromdisk each time it is executed. This saves time for frequentlyused programs like <CODE>ls</CODE>.</P><P>(Solaris 1) If a non-executable file is marked with the sticky bit, itwill <EM>not</EM> be held in the disk page cache -- that is, it is nevercopied from the disk and held in RAM but is written to directly.This is used to prevent certain files from using up valuable memory.</P><P>On some systems (e.g. ULTRIX), only the superuser can set the sticky bit.On others (e.g. SunOS) any user can create a sticky directory.</P><H1><A NAME="SEC69" HREF="unix_toc.html#TOC69">Bourne Again shell</A></H1><P><A NAME="IDX486"></A>The Bourne Again shell (Bash) is the command interpreter which you use to run programs and utilities. It contains a simple programming language for writing tailor-made commands, and allows you to join together UNIX commandswith pipes. It is a configurable environment, and once you know it well,it is the most efficient way of working with UNIX.</P><P>The Bourne Again shell was written by the Free Software Foundation as a part of the GNU project and Bash is the default shell in most GNU/Linux distributions.Because of its command line editing features, it is much more efficient for interactive use than Bourne shell, the original UNIX shell.Most of the system scripts in UNIX are written in the Bourne shell. Although Bash includes many extensions and features not found in the Bourne shell, it maintains compatibility with it so that you can run Bourne shell scripts under Bash. On many GNU/Linux systems Bourne shell (<TT>`/bin/sh'</TT>) is symbolically linked to Bash (<TT>`/bin/bash'</TT>) so that the scripts that require the presence of the Bourne shell still run. If you want to write a platform independent shell script able to run on as many UNIX variants as possible, you should stick to Bourne shell syntax and avoid the Bash extensions. </P><P> </P><H2><A NAME="SEC70" HREF="unix_toc.html#TOC70"><TT>`~/.bashrc'</TT> and <TT>`~/.bash_profile'</TT> files</A></H2><P><A NAME="IDX487"></A><A NAME="IDX488"></A><A NAME="IDX489"></A>When you log on to a GNU/Linux system and your login shell is defined in <TT>`/etc/passwd'</TT> to be Bash, it first executes commands in the <TT>`/etc/profile'</TT> file. It then searches for the <TT>`~/.bash_profile'</TT>, <TT>`~/.bash_login'</TT> or <TT>`~/.profile'</TT> file, in this order, and executes commands in the first of these that is found and is readable. When a login exits, it executes commands in the <TT>`~/.bash_logout'</TT> file.</P><P>When you start an non-login interactive Bash shell, it only executes commands in the <TT>`~/.bashrc'</TT> file, if it exists and is readable. However, this shell inherits any environment (exported) variables from the parent shell, so environment variables set in <TT>`/etc/profile'</TT> and <TT>`~/.bash_profile'</TT> are passed onto the non-login shells and later to its subshells. </P><P>Here is a very simple example <TT>`~/.bashrc'</TT> file:<PRE>## .bashrc - read in by every bash that starts.#umask 077             # Set the default file creation maskPATH="~/bin:$PATH"    # Inserts own bin directory first in PATH<A NAME="IDX490"></A><A NAME="IDX491"></A>PS1="`uname`:\h\$ "  # promptPS2="\h &#62; "          # prompt for foreach and whilePRINTER=myprinter# Aliases are shortcuts to UNIX commandsalias h=historyalias ll="ls -l"alias cp='cp -i'alias rm='rm -i'alias c='ssh cube'</PRE><P>In order to make sure your <TT>`~/.bashrc'</TT> file is read when logging on with <CODE>ssh</CODE> to another machine, you may start your <TT>`~/.bash_profile'</TT> file like this:</P><PRE>## .bash_profile - read in every login.#if [ -f ~/.bashrc ]then   source ~/.bashrc  # runs .bashrc as if they where                      # typed into this filefi</PRE><P> <H2><A NAME="SEC71" HREF="unix_toc.html#TOC71">Variables and export</A></H2><P><A NAME="IDX492"></A><A NAME="IDX493"></A>Shell variables are defined using the syntax<PRE>VARIABLE="username is"myname="`whoami`"</PRE><P>It is  important that there be no space between the variable and theequals sign. These variables are then referred to using the dollar <SAMP>`$'</SAMP> symbol.</P><PRE>$ echo "My $VARIABLE $myname"My username is mark</PRE><P>When assigning values to variables the dollar symbol is never used. By default these variables are <EM>local</EM> - that is they will not be passed on to programs and sub-shells running under the current shell. To make themglobal (so that child processes will inherit them) we use thecommand<PRE>export VARIABLE</PRE><P><A NAME="IDX494"></A>This adds the variable to the process <EM>environment</EM>. Under Bash (but not under the old Bourne shell) it is also possible to declare a variable to be global on a single line by<PRE>export GLOBALVAR="global"</PRE><P>The command<PRE>set -a</PRE><P>changes the default so that all variables, after the command arecreated <EM>global</EM>. </P><P>Arrays or lists are often simulated in Bourne shell by sandwiching the colon <SAMP>`:'</SAMP>symbol between items<PRE>PATH=/bin:/usr/bin:/etc:/local/bin:.LD_LIBARAY_PATH=/usr/lib:/usr/openwin/lib:/local/lib</PRE><P>but there is no real facility for arrays in the Bourne shell. Note thatthe UNIX <SAMP>`cut'</SAMP> command can be used to extract the elements ofthe list. Loops can also read such lists directly See section <A HREF="unix.html#SEC88">Loops in Bash</A>.However, Bash version 2.x supports arrays as seen in the next section.</P><P>The value of a variable is given by the dollar symbol. Itis also possible to use <EM>curly braces</EM> around the variable name to`protect' the variable from interfering text. For example:<PRE>$ animal=worm  $ echo book$animalbookworm$ thing=book$ echo $thingworm                       (nothing..)$ echo ${thing}wormbookworm</PRE><P>Default values can be given to variables in the Bourne shell. Thefollowing commands illustrate this.</P><PRE>echo ${var-"No value set"}echo ${var="Octopus"}echo ${var+"Forced value"}echo ${var?"No such variable"}</PRE><P>The first of these prints out the contents of <SAMP>`$var'</SAMP>, if it isdefined. If it is not defined the variable is substituted for thestring "No value set". The value of <SAMP>`var'</SAMP> is not changed by thisoperation. It is only for convenience.</P><P>The second command has the same effect as the first, but here the valueof <SAMP>`$var'</SAMP> is actually changed to "Octopus" if <SAMP>`$var'</SAMP>is not set.</P><P>The third version is slightly peculiar. If <SAMP>`$var'</SAMP> is <EM>already</EM>set, its value will be forced to be "Forced value", otherwise it isleft undefined.</P><P>Finally the last instance issues an error message "No such variable"if <SAMP>`$var'</SAMP> is not defined.</P><P>In Bash 2.x it is possible to extract parts of the string a variable is set to using the construction <CODE>${variable:offset:length}|</CODE> as shown in the next example.<PRE>var="abcdefg"middle=${var:2:3}echo $middlecde</PRE><P>An offset of 2 skips the first 2 characters and a string of length 3 is extracted from the middle of the string.</P><H2><A NAME="SEC72" HREF="unix_toc.html#TOC72">Bash arrays</A></H2><P>The original Bourne shell does not have arrays. Bash version 2.x does have arrays, however. An array can be assigned from a string of words separated by whitespaces or the individual elements of the array can be set individually.<PRE>colours=(red white green)colours[3]="yellow"</PRE><P>An element of the array must be referred to using curly braces.<PRE>echo ${colours[1]}white</PRE><P>Note that the first element of the array has index 0. The set of all elements is referred to by <CODE>${colours[*]}</CODE>.<PRE>echo ${colours[*]}red white green yellowecho ${#colours[*]}4</PRE><P>As seen the number of elements in an array is given by <CODE>${#colours[*]}</CODE>.</P><P> <H2><A NAME="SEC73" HREF="unix_toc.html#TOC73">Stdin, stdout, stderr and redirection to and from files</A></H2><P>When the shell starts up, it inherits three files: <TT>`stdin'</TT>, <TT>`stdout'</TT>, and <TT>`stderr'</TT>. Standard input normally comes from the keyboard. Standard output and standard error normally go to the screen. There are times you want to read input from a file or send output of errors to a file. This can be accomplished by using <EM>I/O redirection</EM>. </P><P>In Bash and the Bourne shell, the standard input/output files are referred toby numbers rather than by names.<A NAME="IDX495"></A></P><DL COMPACT><DT><EM>stdin</EM><DD>File number 0<DT><EM>stdout</EM><DD>File number 1<DT><EM>stderr</EM><DD>File number 2</DL><P>The default routes for these files can be changed by redirection. The output of the command <CODE>echo</CODE> is by default sent to the screen, that is the stdout with file number 1 is sent to the screen. Using redirection operators it is possible to redirect the standard out of <CODE>echo</CODE> to where we want it. We can send output to a file with the following command.</P><PRE>echo "should be sent to a file" &#62; file.txt</PRE><P>This creates a new file <TT>`file.txt'</TT> containing the string 'should be sent to a file'. The redirection operator could have been given as <CODE>1&#62;</CODE>, but it is understood that standard out is meant when skipping the number of the file handle.The single '&#62;' always creates a new file, while '&#62;&#62;' appends to the end of a file.</P><P>If you had mistyped the command <CODE>echo</CODE> the result would have been:<PRE>ehco "should be sent to a file" &#62; file.txtbash: ehco: command not found</PRE><P>The standard error with file handle 2 is by default sent to the screen, independent of where standard out (1) is sent. If you like you can redirect stdout to another or the same file.<PRE>ehco "should be sent to a file" &#62; file.txt 2&#62; error.txtcat error.txtbash: ehco: command not found</PRE><P>There are several ways to send stderr to the same file as stdin is redirected to. The following three commands are equivalent.<PRE>ehco "should be sent to a file" &#62;&#38; file.txt ehco "should be sent to a file" &#62;  file.txt 2&#62; file.txtehco "should be sent to a file" &#62;  file.txt 2&#62;&#38;1</PRE><P>The string <CODE>2&#62;&#38;1</CODE> means that stderr(2) should be sent to the same file as stdout(1). This is the only why to do this under the Bourne shell and this construction is therefore often seen in system shell scripts.</P><P>Furthermore it is possible to force a command which by default takes standard inputfrom the keyboard, to read input from a file by redirecting stdin. The mail-command expects input from keyboard, but the '&#60;' redirection operator makes it send the password file to the user mark: <PRE>/bin/mail mark &#60; /etc/passwd</PRE><P>The following table summarizes the most important redirection operators:<PRE>Redirection operator    What it does&#60;                       Redirects input&#62;                       Redirects output  &#62;&#62;                      Appends output2&#62;                      Redirects error&#62;&#38;                      Redirects output and error (Bash only)2&#62;&#38;1                    Redirects error where output (1) is going</PRE><P> <H2><A NAME="SEC74" HREF="unix_toc.html#TOC74">Pipes</A></H2><P><A NAME="IDX496"></A></P><P>A <EM>pipe</EM> takes the output from the command on the left-hand side of the pipe symbol and sends it to the input of the command on the right-hand side of the pipe symbol. A pipeline can consist of several pipes and this makes pipes a very powerful tool. It enables us to combine all the small and efficient UNIX commands in any thinkable way. If you want to count the number of people logged on, you could save the output of the command <CODE>who</CODE> in the temporary file <TT>`tmp'</TT>, use <CODE>wc -l</CODE> to count the number of lines in <TT>`tmp'</TT> and finally remove the temporary file.</P><PRE>$ who &#62; tmp$ wc -l tmp      4 tmp$ rm tmp</PRE><P>Using a pipe saves disk space and time: the stdout from <CODE>who</CODE> can be redirected to the stdin of <CODE>wc -l</CODE> through a pipe and there is no need for temporarily storing the output from <CODE>who</CODE>. <PRE>$ who | wc -l       4 </PRE><P>Most UNIX-commands are constructed with piping in mind and this makes it possible to solve complex tasks easily, by joining commands along a pipeline. Consider the following pipeline:</P><PRE>cat big.jpg | djpeg | pnmscale -pixels 150000 | cjpeg &#62; small.jpg</PRE><P>The command <CODE>cat</CODE> sends the large JPEG-image to <CODE>djpeg</CODE> which decompresses it and sends the resulting bitmap to stdout. The stream of data floats through the next pipe to <CODE>pnmscale</CODE> which scales the bitmap image down to the given size. The scaled image is piped to the command <CODE>cjpeg</CODE> which compresses the standard input and finally produces a JPEG-image of reduced size which is stored in the file <TT>`small.jpg'</TT>.</P><H2><A NAME="SEC75" HREF="unix_toc.html#TOC75">Command history</A></H2><P><A NAME="IDX497"></A><A NAME="IDX498"></A>The history feature in Bash means that you do not have to typecommands over and over again. You can use the <KBD>UP ARROW</KBD> key to browse back through the list of commands you have typed previously and the keys <KBD>LEFT ARROW</KBD> and <KBD>RIGHT ARROW</KBD> to edit these commands.</P><P>In addition there are a couple of commands which selects commands from the history list.<DL COMPACT><DT><SAMP>`!!'</SAMP><DD>Execute the last command again.<DT><SAMP>`!4'</SAMP><DD>Execute command number 4.</DL><P>The first of these simply repeats the last command. The second command gives an absolute number. The absolute command numbercan be seen by typing <SAMP>`history'</SAMP>.</P><H2><A NAME="SEC76" HREF="unix_toc.html#TOC76">Command/filename completion</A></H2><P><A NAME="IDX499"></A><A NAME="IDX500"></A><A NAME="IDX501"></A>In Bash you can save hours worthof typing errors by using the completion mechanism. This feature isbased on the <KBD>TAB</KBD> key.</P><P>The idea is that if you type half a filename and press <KBD>TAB</KBD>,the shell will try to guess the remainder of the filename. It doesthis by looking at the files which match what you have already typedand trying to fill in the rest. If there are several files whichmatch, the shell sounds the "bell" or beeps. You can thentype <KBD>TAB</KBD> twice to obtain a list of the possible alternatives.Here is an example: suppose you have just a single file in thecurrent directory called <TT>`very_long_filename'</TT>, typing</P><PRE>more <KBD>TAB</KBD></PRE><P>results in the following appearing on the command line<PRE>more very_long_filename</PRE><P>The shell was able to identify a unique file. Now suppose thatyou have two files called <TT>`very_long_filename'</TT> and <TT>`very_big_filename'</TT>,typing<PRE>more <KBD>TAB</KBD></PRE><P>results in the following appearing on the command line<PRE>more very_</PRE><P>and the shell beeps, indicating that the choice was not unique anda decision is required. Next, you type <KBD>TAB</KBD> twice<A NAME="DOCF3" HREF="unix_foot.html#FOOT3">(3)</A>to see which filesyou have to choose from and the shell lists them and returns you tothe command line, exactly where you were. You now choose<TT>`very_long_filename'</TT> by typing <SAMP>`l'</SAMP>. This is enough touniquely identify the file. Pressing the <KBD>TAB</KBD> key againresults in<PRE>more very_long_filename</PRE><P>on the screen.  As long as you have written enough to select a fileuniquely, the shell will be able to complete the name for you.</P><P>Completion also works on shell commands, but it is a little slower sincethe shell must search through all the directories in the commandpath to complete commands.</P><H2><A NAME="SEC77" HREF="unix_toc.html#TOC77">Single and double quotes</A></H2><P><A NAME="IDX502"></A><A NAME="IDX503"></A><A NAME="IDX504"></A><A NAME="IDX505"></A><A NAME="IDX506"></A><A NAME="IDX507"></A><A NAME="IDX508"></A><A NAME="IDX509"></A></P><P>Two kinds of quotes can be used in shell apart from thebackward quotes we mentioned above. The essential differencebetween them is that certainshell commands work inside <EM>double</EM> quotes but not inside single quotes. For example<PRE>cube$ echo /etc/rc*  /etc/rc.boot /etc/rc0.d /etc/rc1.d /etc/rc2.d /etc/rc3.d /etc/rc4.d cube$ echo "/etc/rc*"  /etc/rc*cube$ echo "`whoami`  -- my name is $USER"mark  -- my name is markcube$ echo '`whoami`  -- my name is $USER'`whoami`  -- my name is $USER</PRE><P>We see that the single quotes prevent <EM>variable substitution</EM>and <EM>sub-shells</EM>. Wildcards do not work inside either single ordouble quotes.</P><H2><A NAME="SEC78" HREF="unix_toc.html#TOC78">Job control, break key, <SAMP>`fg'</SAMP>, <SAMP>`bg'</SAMP></A></H2><P><A NAME="IDX510"></A><A NAME="IDX511"></A><A NAME="IDX512"></A></P><P>So far we haven't mentioned UNIX's ability to multitask. In the Bourneshell (<SAMP>`sh'</SAMP>) there are no facilities for controlling several userprocesses. Bash provides some commands for starting and stopping processes.  These originate from the days before windows and X11, so some of them may seema little old-fashioned. They are still very useful nonetheless.</P><P>Let's begin by looking at the commands which are true for any shell.Most programs are run in the <EM>foreground</EM> or <EM>interactively</EM>.That means that they are connected to the standard input and send theiroutput to the standard output.  A program can be made to run in thebackground, if it does not need to use the standard I/O. For example, aprogram which generates output and sends it to a file could run in thebackground. In a window environment, programs which create their ownwindows can also be started as background processes, leaving standardI/O in the shell free.</P><P><EM>Background processes run independently of what you are doing in the foreground.</EM></P><H3><A NAME="SEC79" HREF="unix_toc.html#TOC79">UNIX Processes and BSD signals</A></H3><P><A NAME="IDX513"></A><A NAME="IDX514"></A><A NAME="IDX515"></A></P><P>A background process is started using the special character <SAMP>`&#38;'</SAMP> atthe end of the command line.<PRE>find / -name '*lib*' -print &#62;&#38; output  &#38;</PRE><P>The final <SAMP>`&#38;'</SAMP> on the end of this line means that the job will berun in the background. Note that this is not confused with theredirection operator <SAMP>`&#62;&#38;'</SAMP> since it must be the last character onthe line. The command above looks for any files in the system containingthe string `lib' and writes the list of files to a file called`output'. This might be a useful way of searching for missing librarieswhich you want to include in your environment variable<SAMP>`LD_LIBRARY_PATH'</SAMP>.  Searching the entire disk from the rootdirectory <SAMP>`/'</SAMP> could take a long time, so it pays to run this in thebackground.</P><P>If we want to see what processes are running, we can use the<SAMP>`ps'</SAMP> command. <SAMP>`ps'</SAMP> without any arguments lists all ofyour processes, i.e. all processes owned by the user name youlogged in with in the current shell. <SAMP>`ps'</SAMP> takes many options, for instance<SAMP>`ps auxg'</SAMP> will list all processes in gruesome detail (The "g" is for group, not gruesome!). <SAMP>`ps'</SAMP> reads the kernel's process tables directly.</P><P>Processes can be stopped and started, or killed one and for all.The <SAMP>`kill'</SAMP> command does this. There are, in fact, two versionsof the <SAMP>`kill'</SAMP> command. One of them is built into Bashand the other is not. If you use Bash then you will nevercare about the difference. We shall nonetheless mention thespecial features of Bash built-ins below. The kill commandtakes a number called a <EM>signal</EM> as an argument and anothernumber called the <EM>process identifier</EM> or <EM>PID</EM> for short.Kill send signals to processes. Some of these are fatal and someare for information only. The two commands</P><PRE>kill -15 127kill 127</PRE><P>are identical. They both send signal 15 to PID 127. This isthe normal <EM>termination</EM> signal and it is often enough tostop any process from running.</P><P>Programs can choose to ignore certain signals by trappingsignals with a special handler. One signal they cannotignore is signal 9.</P><PRE>kill -9  127</PRE><P>is a sure way of killing PID 127. Even though the process dies, itmay not be removed from the kernel's process table if it hasa parent (see next section).</P><P>Here is the complete list of signals which the Linux kernel send toprocesses in different circumstances.</P><PRE>#define SIGHUP     1       /* Hangup (POSIX). */#define SIGINT     2       /* Interrupt (ANSI). */#define SIGQUIT    3       /* Quit (POSIX). */#define SIGILL     4       /* Illegal instruction (ANSI). */#define SIGTRAP    5       /* Trace trap (POSIX). */#define SIGABRT    6       /* Abort (ANSI). */#define SIGIOT     6       /* IOT trap (4.2 BSD). */#define SIGBUS     7       /* BUS error (4.2 BSD). */#define SIGFPE     8       /* Floating-point exception (ANSI). */#define SIGKILL    9       /* Kill, unblockable (POSIX). */#define SIGUSR1    10      /* User-defined signal 1 (POSIX). */#define SIGSEGV    11      /* Segmentation violation (ANSI). */#define SIGUSR2    12      /* User-defined signal 2 (POSIX). */#define SIGPIPE    13      /* Broken pipe (POSIX). */#define SIGALRM    14      /* Alarm clock (POSIX). */#define SIGTERM    15      /* Termination (ANSI). */#define SIGSTKFLT  16      /* Stack fault. */#define SIGCLD     SIGCHLD /* Same as SIGCHLD (System V). */#define SIGCHLD    17      /* Child status has changed (POSIX). */#define SIGCONT    18      /* Continue (POSIX). */#define SIGSTOP    19      /* Stop, unblockable (POSIX). */#define SIGTSTP    20      /* Keyboard stop (POSIX). */#define SIGTTIN    21      /* Background read from tty (POSIX). */#define SIGTTOU    22      /* Background write to tty (POSIX). */#define SIGURG     23      /* Urgent condition on socket (4.2 BSD). */#define SIGXCPU    24      /* CPU limit exceeded (4.2 BSD). */#define SIGXFSZ    25      /* File size limit exceeded (4.2 BSD). */#define SIGVTALRM  26      /* Virtual alarm clock (4.2 BSD). */#define SIGPROF    27      /* Profiling alarm clock (4.2 BSD). */#define SIGWINCH   28      /* Window size change (4.3 BSD, Sun). */#define SIGPOLL    SIGIO   /* Pollable event occurred (System V). */#define SIGIO      29      /* I/O now possible (4.2 BSD). */#define SIGPWR     30      /* Power failure restart (System V). */#define SIGSYS     31      /* Bad system call. */</PRE><P>We have already mentioned 15 and 9 which are the main signalsfor users. Signal 1, or <SAMP>`HUP'</SAMP> can be sent to certain programsby the superuser. For instance<PRE>kill -1   &#60;inetd&#62;kill -HUP &#60;inetd&#62;</PRE><P>which forces <SAMP>`inetd'</SAMP> to reread its configuration file. Sometimesit is useful to <EM>suspend</EM> a process temporarily and then<EM>restart</EM> it later. <PRE>kill -20 &#60;PID&#62;       # suspend process &#60;PID&#62;kill -18 &#60;PID&#62;       # resume process &#60;PID&#62;</PRE><H3><A NAME="SEC80" HREF="unix_toc.html#TOC80">Child Processes and zombies</A></H3><P>When you start a process from a shell, regardless of whether it isa background process or a foreground process, the new process becomesa <EM>child</EM> of the original shell. Remember that the shell is justa UNIX process itself. Moreover, if one of the children starts a newprocess then it will be a child of the child (a grandchild?)! Processes therefore form<EM>hierarchies</EM>. Several children can have a common <EM>parent</EM>.</P><P>If we kill a parent, then (unless the child has detached itself from theparent) all of its children die too. If a child dies, the parent is notaffected. Sometimes when a child is killed, it does not die but becomes"defunct" or a zombie process. This means that the child has a parentwhich is <EM>waiting</EM> for it to finish. If the parent has not yet beeninformed that the child has died, for example because it has beensuspended itself, then the dead child is not removed from the kernel'sprocess table. When the parent wakes up and receives the message thatthe child has terminated, the process entry for the dead child can beremoved.</P><H3><A NAME="SEC81" HREF="unix_toc.html#TOC81">Bash builtins: <SAMP>`jobs'</SAMP>, <SAMP>`kill'</SAMP>, <SAMP>`fg'</SAMP>,<SAMP>`bg'</SAMP>, break key</A></H3><P><A NAME="IDX516"></A><A NAME="IDX517"></A><A NAME="IDX518"></A><A NAME="IDX519"></A></P><P>Now let's look at some commands which are built into Bash forstarting and stopping processes.  Bash refers to user programs as`jobs' rather than processes -- but there is no real difference. Theadded bonus of Bash is that each shell has a <EM>job number</EM> inaddition to its PID. The job numbers are simpler and are private for theshell, whereas the PIDs are assigned by the kernel and are often verylarge numbers which are difficult to to remember. When a command isexecuted in the shell, it is assigned a job number. If you never run anybackground jobs then there is only ever one job number: 1, since everyjob exits before the next one starts. However, if you run backgroundtasks, then you can have several jobs "active" at any time. Moreover, by<EM>suspending</EM> jobs, Bash allows you to have several interactiveprograms running on the same terminal -- the <SAMP>`fg'</SAMP> and <SAMP>`bg'</SAMP>commands allow you to move commands from the background to theforeground and vice-versa.</P><P>Take a look at the following shell session.<PRE>cube$ emacs myfile&#38;[3] 771cube$   ( other commands ... , edit myfile and close emacs )</PRE><P>When a background job is done, the shell prints a message at a suitablemoment between prompts.</P><PRE>[3]+  Done                    emacs myfilecube$ </PRE><P>This tells you that job number 1 finished normally. If the jobexits abnormally then the word `Done' may be replaced by some othermessage. For instance, if you kill the job, it will say <A NAME="IDX520"></A><PRE>cube$ kill %3cube$ [3]+  Terminated              emacs myfilecube$ </PRE><P>You can list the jobs you have running using the <SAMP>`jobs'</SAMP> command.The output looks something like<PRE>cube$ jobs[1]   Terminated              xdvi unix[2]   Running                 xemacs unix.texinfo &#38;[3]   Running                 xterm -sb -sl 10000 &#38;[4]   Running                 ghostview &#38;[5]   Running                 netscape &#38;[6]   Running                 xterm -sb -sl 10000 &#38;[7]   Running                 xemacs fil &#38;[8]+  Stopped                 emacs unix.log[9]-  Running                 gimp &#38;</PRE><P><A NAME="IDX521"></A><A NAME="IDX522"></A><A NAME="IDX523"></A><A NAME="IDX524"></A></P><P>To suspend a program which you are running in the foreground you can type <KBD>CTRL-z</KBD> (this is like sending a <SAMP>`kill -20'</SAMP>signal from the keyboard).  <A NAME="DOCF4" HREF="unix_foot.html#FOOT4">(4)</A>  You can suspend any number of programs and then restart themone at a time using <SAMP>`fg'</SAMP> and <SAMP>`bg'</SAMP>. If you want job 5 to berestarted in the foreground, you would type</P><PRE>fg %5</PRE><P>When you have had enough of job 5, you can type CTRL-z to suspend itand then type</P><P><PRE>fg %6</PRE><P>to activate job 6.  Provided a job does not want to send output to<SAMP>`stdout'</SAMP>, you can restart any job in the background, using acommand like.<PRE>bg %4</PRE><P><EM>This method of working was useful before windows were available.</EM><EM>Using <SAMP>`fg'</SAMP> and <SAMP>`bg'</SAMP>, you can edit several files</EM><EM>or work on several programs without have to quit to</EM><EM>move from one to another.</EM></P><P>See also some related commands forbatch processing <SAMP>`at'</SAMP>, <SAMP>`batch'</SAMP> and <SAMP>`atq'</SAMP>, <SAMP>`cron'</SAMP>.</P><P><A NAME="IDX525"></A><A NAME="IDX526"></A>NOTE: <KBD>CTRL-c</KBD> sends a <SAMP>`kill -2'</SAMP> signal, which send a standardinterrupt message to a program. This is always a safe way to interrupta shell command.</P><P> <H2><A NAME="SEC82" HREF="unix_toc.html#TOC82">Arithmetic in Bash</A></H2><P><A NAME="IDX527"></A></P><P>In Bourne shell arithmetic is performed entirely `by proxy'. To evaluate an expression we call the <SAMP>`expr'</SAMP> command or the <SAMP>`bc'</SAMP>precision calculator. Here are some examples of <SAMP>`expr'</SAMP><PRE>a=`expr $a+1`                 # increment aa=`expr 4 + 10 \* 5`          # 4+10*5check = `expr $a \&#62; $b`       # true=1, false=0. True if $a &#62; $b</PRE><P><SAMP>`expr'</SAMP> is very sensitive to spaces and backslash characters and this makes it a bit awkward to do arithmetic under the Bourne shell. </P><P>Bash 2.0 provides a new and simpler way to do arithmetic using double parentheses. If you surround any integer arithmetic expression as in <CODE>(( x = y + 1 ))</CODE>, you can perform most arithmetic operations with the same syntax as in Java and C.<PRE>(( x = 1 ))echo $x1(( x++ ))(( y = 4*x ))echo $y8</PRE><P>Note that you do not need to use the dollar symbol to refer to a variable within the double parentheses (but you may do it) and that spaces are allowed. <PRE>(( sum = 2 ))(( total = 4*$sum + sum ))echo $total10</PRE><P>The variables within double parentheses are throughout treated as integers. Assigning a float value like 2.5 to a variable results in an syntax error while assigning a string to a variable cause the string to be stored as zero. <H2><A NAME="SEC83" HREF="unix_toc.html#TOC83">Scripts and arguments</A></H2><P>Scripts are created by making an executable file which beginswith the sequence of characters</P><P><A NAME="IDX528"></A><A NAME="IDX529"></A><A NAME="IDX530"></A></P><PRE>#!/bin/bash</PRE><P>This construction is quitegeneral: any executable file which begins with a sequence<PRE>#!myprogram -option</PRE><P>will cause the shell to attempt to execute<PRE>myprogam -option filename</PRE><P>where <VAR>filename</VAR> is the name of the file.</P><P><A NAME="IDX531"></A></P><P>If a script is to accept arguments then these can be referred to as<SAMP>` $1 $2 $3..$9'</SAMP>. There is a logical limit of nine arguments toa Bourne script, but Bash handles the next arguments as <SAMP>`${10}'</SAMP>.<SAMP>`$0'</SAMP> is the name of the script itself.</P><P>Here is a simple Bash script which prints outall its arguments.<A NAME="IDX532"></A><PRE>#!/bin/bash# # Print all arguments (version 1)#for arg in $*do  echo Argument $argdoneecho Total number of arguments was $#</PRE><P>The <SAMP>`$*'</SAMP> symbol stands for the entire list of arguments and <SAMP>`$#'</SAMP> is the total number of arguments.</P><P>Another way of achieving the same is to use the <SAMP>`shift'</SAMP> command.We shall meet this again in the Perl programming language. <SAMP>`shift'</SAMP>takes the first argument from the argument list and deletes it, movingall of the other arguments down one number -- this is how we canhandle long lists of arguments in the Bourne shell.<A NAME="IDX533"></A><A NAME="IDX534"></A></P><PRE>#!/bin/bash##  Print all arguments (version 2)#while ( true )do  arg=$1;  shift;  echo $arg was an argument;  if [ $# -eq 0 ]; then    break  fidone</PRE><P> <H2><A NAME="SEC84" HREF="unix_toc.html#TOC84">Return codes</A></H2><P><A NAME="IDX535"></A><A NAME="IDX536"></A></P><P>All programs which execute in UNIX return a value through the C <SAMP>`return'</SAMP> command. There is a convention that a return valueof zero (0) means that everything went well, whereas anyother value implies that some error occurred. The returnvalue is usually the value returned in <SAMP>`errno'</SAMP>, theexternal error variable in C.</P><P>Shell scripts cantest for these values either by placing the commanddirectly inside an `if' test, or by testing the variable <SAMP>`$?'</SAMP>which is always set to the return code of the last command.Some examples are given following the next two sections.</P><P> <H2><A NAME="SEC85" HREF="unix_toc.html#TOC85">Tests and conditionals</A></H2><P><A NAME="IDX537"></A></P><P>Bash and the Bourne shell has an array of tests. They are written asfollows. Notice that <SAMP>`test'</SAMP> is itself not a part of the shell,but is a program which works out conditions and provides a returncode. See the manual page on <SAMP>`test'</SAMP> for more details.</P><P><A NAME="IDX538"></A><A NAME="IDX539"></A><A NAME="IDX540"></A><A NAME="IDX541"></A><A NAME="IDX542"></A><A NAME="IDX543"></A><A NAME="IDX544"></A><A NAME="IDX545"></A><A NAME="IDX546"></A><A NAME="IDX547"></A><A NAME="IDX548"></A><A NAME="IDX549"></A><A NAME="IDX550"></A><A NAME="IDX551"></A><A NAME="IDX552"></A><A NAME="IDX553"></A><A NAME="IDX554"></A><A NAME="IDX555"></A><A NAME="IDX556"></A></P><DL COMPACT><DT><CODE>test -f <VAR>file</VAR></CODE><DD>True if the file is a plain file <DT><CODE>test -d <VAR>file</VAR></CODE><DD>True if the file is a directory<DT><CODE>test -r <VAR>file</VAR></CODE><DD>True if the file is readable<DT><CODE>test -w <VAR>file</VAR></CODE><DD>True if the file is writable<DT><CODE>test -x <VAR>file</VAR></CODE><DD>True if the file is executable<DT><CODE>test -s <VAR>file</VAR></CODE><DD>True if the file contains something<DT><CODE>test -g <VAR>file</VAR></CODE><DD>True if setgid bit is set<DT><CODE>test -u <VAR>file</VAR></CODE><DD>True if setuid bit is set<DT><CODE>test s1 = s2</CODE><DD>True if strings s1 and s2 are equal<DT><CODE>test s1 != s2</CODE><DD>True if strings s1 and s2 are unequal<DT><CODE>test <VAR>x</VAR> -eq <VAR>y</VAR></CODE><DD>True if the integers <VAR>x</VAR> and <VAR>y</VAR> are numerically equal<DT><CODE>test <VAR>x</VAR> -ne <VAR>y</VAR></CODE><DD>True if integers are not equal<DT><CODE>test <VAR>x</VAR> -gt <VAR>y</VAR></CODE><DD>True if <VAR>x</VAR> is greater than <VAR>y</VAR><DT><CODE>test <VAR>x</VAR> -lt <VAR>y</VAR></CODE><DD>True if <VAR>x</VAR> is less than <VAR>y</VAR><DT><CODE>test <VAR>x</VAR> -ge <VAR>y</VAR></CODE><DD>True if <VAR>x</VAR>&#62;=<VAR>y</VAR><DT><CODE>test <VAR>x</VAR> -le <VAR>y</VAR></CODE><DD> True if <VAR>x</VAR> &#60;= <VAR>y</VAR><DT><CODE>!</CODE><DD>Logical NOT operator<DT><CODE>-a</CODE><DD>Logical AND<DT><CODE>-o</CODE><DD>Logical OR</DL><P>Note that an alternate syntax for writing these commands if to use thesquare brackets, instead of writing the word test.<A NAME="IDX557"></A><A NAME="IDX558"></A><PRE> [ $x -lt $y ]   "=="    test $x -lt $y</PRE><P>Just as with the arithmetic expressions, Bash 2.x provides a syntax for conditionals which are more similar to Java and C. While arithmetic C-like expressions can be used within double parentheses, C-like tests can be used within double square brackets.<PRE> [[ $var == "OK" || $var == "yes" ]]</PRE><P>This C-like syntax is not allowed in the Bourne shell, but is equivalent to <PRE>[ $var = "OK" -o $var = "yes" ]</PRE><P>which is valid in both shells.</P><P>Arithmetic C-like tests can be used within double parentheses so that under Bash 2.x the following tests are equivalent:<PRE> [ $x -lt $y ]   "==" (( x &#60; y ))</PRE><P><A NAME="IDX559"></A></P><P> <H2><A NAME="SEC86" HREF="unix_toc.html#TOC86">Conditional structures</A></H2><P>The conditional structures have the following syntax.<PRE>if <VAR>UNIX-command</VAR>then   <VAR>command</VAR>else   <VAR>commands</VAR>fi</PRE><P>The <SAMP>`else'</SAMP> clause is, of course, optional.As noted before, the first UNIX command could be <EM>anything</EM>, sinceevery command has a return code. The result is TRUE if it evaluatesto <EM>zero</EM> and false otherwise (in contrast to the conventions in mostlanguages). Multiple tests can be made using<PRE>if <VAR>UNIX-command</VAR>then   <VAR>commands</VAR>elif <VAR>UNIX-command</VAR>then   <VAR>commands</VAR>elif <VAR>UNIX-command</VAR>then   <VAR>commands</VAR>else   <VAR>commands</VAR>fi</PRE><P>where <SAMP>`elif'</SAMP> means `else-if'.</P><P>The equivalent of the C-school's <SAMP>`switch'</SAMP> statement is a morePascal-like <SAMP>`case'</SAMP> structure.<PRE>case <VAR>UNIX-command-or-variable</VAR> in   wildcard1) <VAR>commands</VAR> ;;   wildcard2) <VAR>commands</VAR> ;;   wildcard3) <VAR>commands</VAR> ;;esac</PRE><P>This structure uses the wildcards to match the output of the commandor variable in the first line. The first pattern which matches getsexecuted.</P><P> <H2><A NAME="SEC87" HREF="unix_toc.html#TOC87">Input from the user in Bash</A></H2><P>In shell you can read the value of a variable using the <SAMP>`read'</SAMP>command, with syntax</P><PRE>read <VAR>variable</VAR></PRE><P>This reads in a string from the keyboard and terminates on a newlinecharacter. Under the old Bourne shell another way to do this is to use the <SAMP>`input'</SAMP> command to access a particular logical device. The keyboard devicein the current terminal is <TT>`/dev/tty'</TT>, so that one writes<PRE><VAR>variable</VAR> = `line &#60; /dev/tty`</PRE><P>which fetches a single line from the user. The command <CODE>line</CODE> is however not available in most GNU/Linux distributions. </P><P><A NAME="IDX560"></A>Here are some examples of these commands.First a program which asks yes or no...<PRE>#!/bin/bash## Yes or no#echo "Please answer yes or no: "read answercase $answer in  y* | Y* | j* | J* )  echo YES!! ;;  n* | N* )            echo NO!! ;;  *)                   echo "Can't you answer a simple question?"esacecho The end</PRE><P>Notice the use of pattern matching and the <SAMP>`|'</SAMP> `OR' symbol.<PRE>#!/bin/bash## Kernel check#if test ! -f /vmUNIX          # Check that the kernel is there!then   echo "This is not BSD UNIX...hmmm"   if [ -f /hp-ux ]   then      echo "It's a Hewlett Packard machine!"   fielif [ -w /vmUNIX ]then   echo "HEY!! The kernel is writable my me!";else   echo "The kernel is write protected."   echo "The system is safe from me today."fi</PRE><P> <H2><A NAME="SEC88" HREF="unix_toc.html#TOC88">Loops in Bash</A></H2><P><A NAME="IDX561"></A><A NAME="IDX562"></A></P><P>The loop structures in Bash and in the Bourne shell have the following syntax.<PRE>while <VAR>UNIX-command</VAR>do  commandsdone</PRE><P>The first command will most likely be a test but, as before, itcould in principle be any UNIX command. The <SAMP>`until'</SAMP> loop,reminiscent of BCPL, carries out a task until its argument evaluatesto TRUE.<PRE>until <VAR>UNIX-command</VAR>do    commandsdone</PRE><P><A NAME="IDX563"></A>Finally the <SAMP>`for'</SAMP> structure has already been used above.<PRE>for <VAR>variable</VAR> in <VAR>list</VAR>do   <VAR>commands</VAR>done</PRE><P>Often we want to be able to use an array of values as the list which<CODE>for</CODE> parses, but Bourne shell has no array variables. Thisproblem is usually solved by making a long string separated by, forexample, colons. For example, the <CODE>$PATH</CODE> variable has theform<PRE>PATH = /usr/bin:/bin:/local/gnu/bin</PRE><P><A NAME="IDX564"></A><A NAME="IDX565"></A><A NAME="IDX566"></A>Bourne shell allows us to split such a string on whatever characterwe wish. Normally the split is made on spaces, but the variable<SAMP>`IFS'</SAMP> can be defined with a replacement. To make a loop overall directories in the command path we would therefore write<PRE>IFS=:for name in $PATH; do   <VAR>commands</VAR>done</PRE><P>The best way to gain experience with these commands is through someexamples.<PRE>#!/bin/bash## Get text from user repeatedly#echo "Type away..."while read TEXTdo   echo You typed $TEXT   if [ "$TEXT" = "quit" ]; then      echo "(So I quit!)"      exit 0   fidoneecho "HELP!"</PRE><P><A NAME="IDX567"></A><A NAME="IDX568"></A>This very simple script is a typical use for a while-loop. Itgets text repeatedly until the user type `quit'. Since readnever returns `false' unless an error occurs or it detectsan EOF (end of file) character <KBD>CTRL-D</KBD>, it will neverexit without some help from an `if' test. If it does receivea <KBD>CTRL-D</KBD> signal, the script prints `HELP!'.</P><PRE>#!/bin/bash## Watch in the background for a particular user# and give alarm if he/she logs in## To be run in the background, using &#38;#if [ $# -ne 1 ]; then  echo "Give the name of the user as an argument" &#62; /dev/tty  exit 1fiecho "Looking for $1"until users | grep -s $1do   sleep 60doneecho "!!! WAKE UP !!!" &#62; /dev/ttyecho "User $1 just logged in" &#62; /dev/tty</PRE><P>This script uses <SAMP>`grep'</SAMP> in `silent mode' (-s option). i.e. grep neverwrites anything to the terminal. The only thing we are interestedin is the return code the piped command produces. If `grep'detects a line containing the username we are interested in,then the result evaluates to TRUE and the sleep-loop exits.</P><P>Our final example is the kind of script which is useful fora system administrator. It transfers over the Network InformationService database files so that a slave server is up to date.All we have to do is make a list of the files and place it in a<SAMP>`for'</SAMP> loop. The names used below are the actual namesof the NIS maps, well known to system administrators.<PRE>#!/bin/bash## Update the NIS database maps on a client server. This program# shouldn't have to be run, but sometimes things go wrong and we# have to force a download from the main sever.#PATH=/etc/yp:/usr/etc/yp:$PATHMASTER=myNISserverfor map in auto.direct auto.master ethers.byaddr ethers.byname\           group.bygid group.byname hosts.byaddr hosts.byname\           mail.aliases netgroup.byhost netgroup.byuser netgroup\           netid.byname networks.byaddr networks.byname passwd.byname\           passwd.byuid priss.byname protocols.byname protocols.bynumber\           rpc.bynumber services.byname services usenetgroups.byname;do  ypxfr $1 -h $MASTER $mapdone</PRE><P> <H2><A NAME="SEC89" HREF="unix_toc.html#TOC89">Procedures and traps</A></H2><P><A NAME="IDX569"></A><A NAME="IDX570"></A><A NAME="IDX571"></A><A NAME="IDX572"></A></P><P>One of the worthy features of the Bourne shell is that it allowsyou to define <EM>subroutines</EM> or <EM>procedures</EM>. Subroutineswork just like subroutines in any other programming language. They areexecuted in same shell (not as a sub-process).</P><P>Here is an interesting program which demonstrates two usefulthings at the same time. First of all, it shows how to makea hierarchical subroutine structure using the Bourne shell.Secondly, it shows how the <SAMP>`trap'</SAMP> directive can be usedto trap signals, so that Bourne shell programs can exit safelywhen they are killed or when CTRL-C is typed.</P><PRE>#!/bin/bash##  How to make a signal handler in Bourne Shell#  using subroutines####################################################### Level 2#####################################################ReallyQuit(){while truedo  echo "Do you really want to quit?"  read answer  case $answer in     y* | Y* ) return 0;;     *)        echo "Resuming..."               return 1;;  esacdone}###################################################### Level 1#####################################################SignalHandler(){if ReallyQuit           # Call a functionthen   exit 0else   return 0fi}###################################################### Level 0 : main program#####################################################trap SignalHandler 2 15  # Trap kill signals 2 and 15echo "Type some lines of text..."while read textdo   echo "$text - CTRL-C to exit"done</PRE><P>Note that the logical tree structure of this program is upside down(the highest level comes at the bottom). This is because all subroutinesmust be defined before they are used.</P><P>This example concludes our survey of Bash and the Bourne shell.</P><P> <H2><A NAME="SEC90" HREF="unix_toc.html#TOC90">setuid and setgid scripts</A></H2><P><A NAME="IDX573"></A><A NAME="IDX574"></A></P><P>The superuser <SAMP>`root'</SAMP> is the only privileged user in UNIX. All otherusers have only restricted access to the system. Usually this is desirable,but sometimes it is a nuisance.</P><P>A setuid script is a script which has its <EM>setuid-bit</EM> set.  Whensuch a script is executed by a user, it is run with all the rights andprivileges of the owner of the script. All of the commands in the scriptare executed as the owner of the file and not with the user-id of the person who ranthe script. If the owner of the setuid script is <SAMP>`root'</SAMP> then thecommands in the script are run with <EM>root privileges</EM>!</P><P>Setuid scripts are clearly a touchy security issue. When givingaway one's rights to another user (especially those of <SAMP>`root'</SAMP>)one is tempting hackers. Setuid scripts should be <EM>avoided</EM>.</P><P>A setgid program is almost the same, but only the group id is set tothat of the owner of the file. Often the effect is the same.</P><P>An example of a setuid program is the <SAMP>`ps'</SAMP> program. <SAMP>`ps'</SAMP>lists all of the processes running in the kernel. In order todo this it needs permission to access the private data structuresin the kernel. By making <SAMP>`ps'</SAMP> setgid root, it allows ordinaryusers to be able to read as much as the writers of <SAMP>`ps'</SAMP>thought fit, but no more.</P><P>Naturally, only the superuser can make a file setuid or setgid root.</P><P> <H2><A NAME="SEC91" HREF="unix_toc.html#TOC91">Exercises</A></H2><OL><LI>Write an improved <SAMP>`which'</SAMP> command in Bash.<LI>Make a counter program which records in a file how many timesyou log in to your account. You can call this in your .bashrc file.<LI>Make a Bourne shell script to kill all the processes owned by a particularuser. (Note, that if you are not the superuser, you cannot kill processesowned by other users.)<LI>Write a script to replace the <SAMP>`rm'</SAMP> command with somethingsafer. Think about a way of implementing <SAMP>`rm'</SAMP> so that it ispossible to get deleted files back again in case of emergencies. This isnot possible using the normal <SAMP>`rm'</SAMP> command. Hint: save filesin a hidden directory <SAMP>`.deleted'</SAMP>. Make your script deletefiles in the <SAMP>`.deleted'</SAMP> directory if they are older thana week, so that you don't fill up the disk with rubbish.<LI>Suppose you have a bunch of files with a particular file-extension:write a script in Bash to change the extension to something else. e.g.to change *.C into *.c. Give the old and new extensions as arguments tothe script.<LI>Write a program in Bash to search for files in the current directorywhich contain a certain string. e.g. search for all files which containthe word "if". Hint: use the "find" command.<LI>Use the manual pages to find out about the commands <SAMP>`at'</SAMP>,<SAMP>`batch'</SAMP> and <SAMP>`atq'</SAMP>. Test these commands by executing theshell command <SAMP>`date'</SAMP> at some time of your choice. Use the <SAMP>`-m'</SAMP>option so that the result of the job is mailed to you.<A NAME="IDX575"></A><A NAME="IDX576"></A><LI>Write a script in Bash to list all of the files biggerthan a certain size starting from the current directory, and includingall subdirectories. This kind of program is useful for system administratorswhen a disk becomes full.</OL><H1><A NAME="SEC92" HREF="unix_toc.html#TOC92">C shell</A></H1><P>Programmers who are used to C or C++ often find it easier to program inC-shell because there are strong similarities between the two. </P><H2><A NAME="SEC93" HREF="unix_toc.html#TOC93">.cshrc and .login files</A></H2><P><A NAME="IDX577"></A><A NAME="IDX578"></A><A NAME="IDX579"></A><A NAME="IDX580"></A><A NAME="IDX581"></A></P><P>Most users run the C-shell <TT>`/bin/csh'</TT> as their login environment,or these days, preferably the <TT>`tcsh'</TT> which is an improved versionof csh.  When a user logs in to a UNIX system the C-shell starts byreading some files which configure the environment by definingvariables like <CODE>path</CODE>.</P><UL><LI>The file <TT>`.cshrc'</TT> is searched for in your home directory.i.e. <TT>`~/.cshrc'</TT>.  If it is found, its contents are interpreted bythe C-shell as C-shell instructions, before giving you the commandprompt<A NAME="DOCF5" HREF="unix_foot.html#FOOT5">(5)</A>.<LI>If and only if this is the <EM>login shell</EM> (not a sub-shell thatyou have started after login) then the file <TT>`~/.login'</TT> is searchedfor and executed.</UL><P>With the advent of the X11 windowing system, this has changed slightly.Since the window system takes over the entire login procedure, usersnever get to run `login shells', since the login shell is used upby the X11 system. On an X-terminal or host running X the <TT>`.login'</TT> filenormally has no effect. </P><P>With some thought, the <TT>`.login'</TT> file can be eliminated entirely,and we can put everything into the <CODE>.cshrc</CODE>  file.Here is a very simple example <TT>`.cshrc'</TT> file.</P><PRE>## .cshrc - read in by every csh that starts.## Set the default file creation maskumask 077# Set the pathset path=( /usr/local/bin /usr/bin/X11 /usr/ucb /bin /usr/bin . )# Exit here if the shell is not interactiveif ( $?prompt == 0 ) exit# Set some variablesset noclobber notify filec nobeepset history=100<A NAME="IDX582"></A><A NAME="IDX583"></A>set prompt="`hostname`%"set prompt2 = "%m %h&#62;"    # tcsh, prompt for foreach and whilesetenv PRINTER myprintersetenv LD_LIBRARY_PATH /usr/lib:/usr/local/lib:/usr/openwin/lib# Aliases are shortcuts to UNIX commandsalias passwd  yppasswdalias dir     'ls -lg \!* | more'alias sys     'ps aux | more'alias h       history</PRE><P>It is possible to make a much more complicated .cshrc file than this.The advent of distributed computing and NFS (Network file system)means that you might log into many different machines runningdifferent versions of UNIX. The command path would have to be setdifferently for each type of machine.</P><H2><A NAME="SEC94" HREF="unix_toc.html#TOC94">Defining variables with set, setenv</A></H2><P>We have already seen in the examples above how to define variables inC-shell. Let's formalize this. To define a local variable -- that is,one which will not get passed on to programs and sub-shells runningunder the current shell, we write</P><PRE>set local = "some string"set myname = "`whoami`"</PRE><P>These variables are then referred to by using the dollar <SAMP>`$'</SAMP> symbol.i.e. The value of the variable <SAMP>`local'</SAMP> is <SAMP>`$local'</SAMP>.</P><PRE>echo $local $myname</PRE><P>Global variables, that is variables which all sub-shells inherit fromthe current shell are defined using <SAMP>`setenv'</SAMP></P><PRE>setenv GLOBAL "Some other string"setenv MYNAME "`who am i`"</PRE><P>Their values are also referred to using the <SAMP>`$'</SAMP> symbol. Notice that<CODE>set</CODE> uses an <SAMP>`='</SAMP> sign while <SAMP>`setenv'</SAMP> does not.<A NAME="IDX584"></A><A NAME="IDX585"></A><A NAME="IDX586"></A><A NAME="IDX587"></A></P><P>Variables can be also created without a value. The shell uses thismethod to switch on and off certain features, using variableslike <SAMP>`noclobber'</SAMP> and <SAMP>`noglob'</SAMP>. For instance<PRE>nexus% set flagnexus% if ($?flag) echo 'Flag is set!'Flag is set!nexus% unset flagnexus% if ( $?flag ) echo 'Flag is set!'nexus% </PRE><P>The operator <SAMP>`$?<VAR>variable</VAR>'</SAMP> is <SAMP>`true'</SAMP> if <VAR>variable</VAR>exists and <SAMP>`false'</SAMP> if it does not. It does not matter whetherthe variable holds any information.<A NAME="IDX588"></A><A NAME="IDX589"></A><A NAME="IDX590"></A></P><P>The commands <SAMP>`unset'</SAMP> and <SAMP>`unsetenv'</SAMP> can be used to undefineor delete variables when you don't want them anymore.<A NAME="IDX591"></A></P><H2><A NAME="SEC95" HREF="unix_toc.html#TOC95">Arrays</A></H2><P><A NAME="IDX592"></A><A NAME="IDX593"></A><A NAME="IDX594"></A></P><P>A useful facility in the C-shell is the ability to make arrays out ofstrings and other variables. The round parentheses <SAMP>`(..)'</SAMP> do this.For example, look at the following commands.<PRE>nexus% set array = ( a b c d )nexus% echo $array[1]anexus% echo $array[2]bnexus% echo $array[$#array]dnexus% set noarray = ( "a b c d" )nexus% echo $noarray[1]a b c dnexus% echo $noarray[$#noarray]a b c d</PRE><P>The first command defines an array containing the elements <SAMP>`a b c d'</SAMP>.The elements of the array are referred to using square brackets <SAMP>`[..]'</SAMP>and the first element is <SAMP>`$array[1]'</SAMP>. The last element is <SAMP>`$array[4]'</SAMP>. <EM>NOTE: this is not the same as in C or C++ wherethe first element of the array is the zeroth element!</EM></P><P>The special operator <SAMP>`$#'</SAMP> returns the number of elements in an array.This gives us a simple way of finding the end of the array.For example<PRE>nexus% echo $#path23nexus% echo "The last element in path is $path[$#path]"The last element in path is .</PRE><P>To find the next last element we need to be able to do arithmetic. We'llcome back to this later.</P><H2><A NAME="SEC96" HREF="unix_toc.html#TOC96">Pipes and redirection in csh</A></H2><P><A NAME="IDX595"></A><A NAME="IDX596"></A><A NAME="IDX597"></A><A NAME="IDX598"></A><A NAME="IDX599"></A><A NAME="IDX600"></A><A NAME="IDX601"></A><A NAME="IDX602"></A><A NAME="IDX603"></A><A NAME="IDX604"></A></P><P>The symbols <PRE>              &#60;  &#62;  &#62;&#62;  &#60;&#60;  |  &#38;</PRE><P>have a special meaning in the shell. By default, most commands take theirinput from the file <SAMP>`stdin'</SAMP> (the keyboard) and writetheir output to the file <SAMP>`stdout'</SAMP> and their error messages to thefile <SAMP>`stderr'</SAMP> (normally, both of these output files are defined to bethe current terminal device <SAMP>`/dev/tty'</SAMP>, or <SAMP>`/dev/console'</SAMP>).</P><P><SAMP>`stdin'</SAMP>, <SAMP>`stdout'</SAMP> and <SAMP>`stderr'</SAMP>, known collectively as<SAMP>`stdio'</SAMP>, can be redefined or <EM>redirected</EM> so that information is taken fromor sent to a different file. The output direction can bechanged with the symbol <SAMP>`&#62;'</SAMP>. For example,</P><P><A NAME="IDX605"></A><PRE>echo testing &#62; myfile</PRE><P>produces a file called <TT>`myfile'</TT> which contains the string `testing'.The single <SAMP>`&#62;'</SAMP> (greater than) sign always creates a new file, whereasthe double <SAMP>`&#62;&#62;'</SAMP> appends to the end of a file, if it already exists.So the first of the commands<PRE>echo blah blah &#62;&#62; myfileecho Newfile &#62; myfile</PRE><P>adds a second line to <SAMP>`myfile'</SAMP> after `testing', whereas the secondcommand writes over <TT>`myfile'</TT> and ends up with just one line`Newfile'.</P><P>Now suppose we mistype a command<PRE>ehco test &#62; myfile</PRE><P>The command <SAMP>`ehco'</SAMP> does not exist and so the error message<SAMP>`ehco: Command not found'</SAMP> appears on the terminal. This errormessage was sent to <EM>stderr</EM> -- so even though we redirected outputto a file, the error message appeared on the screen to tell us thatan error occurred. Even this can be changed. <SAMP>`stderr'</SAMP> can alsobe redirected by adding an ampersand <SAMP>`&#38;'</SAMP> character to the <SAMP>`&#62;'</SAMP> symbol. The command<PRE>ehco test &#62;&#38; myfile</PRE><P>results in the file <TT>`myfile'</TT> being created, containing theerror message `ehco: Command not found'.</P><P>The input direction can be changed using the <SAMP>`&#60;'</SAMP> symbolfor example<PRE>/bin/mail mark &#60; message</PRE><P>would send the file <SAMP>`message'</SAMP> to the user <SAMP>`mark'</SAMP> byelectronic mail. The mail program takes its input from the fileinstead of waiting for keyboard input.</P><P><A NAME="IDX606"></A><A NAME="IDX607"></A><A NAME="IDX608"></A>There are some refinements to the redirection symbols. First of all,let us introduce the C-shell variable <SAMP>`noclobber'</SAMP>. If this variableis set with a command like<PRE>set noclobber</PRE><P>then files will not be overwritten by the <SAMP>`&#62;'</SAMP> command. If onetries to redirect output to an existing file, the following happens.<PRE>UNIX% set noclobberUNIX% touch blah        # create an empty file blahUNIX% echo test &#62; blahblah: File exists.</PRE><P>If you are nervous about overwriting files, then you can set <SAMP>`noclobber'</SAMP>in your <TT>`.cshrc'</TT> file. <SAMP>`noclobber'</SAMP> can be overridden usingthe pling <SAMP>`!'</SAMP> symbol. So<PRE>UNIX% set noclobberUNIX% touch blah        # create an empty file blahUNIX% echo test &#62;! blah</PRE><P>writes over the file <SAMP>`blah'</SAMP> even though <SAMP>`noclobber'</SAMP> is set.</P><P>Here are some other combinations of redirection symbols</P><P><A NAME="IDX609"></A><DL COMPACT><DT><SAMP>`&#62;&#62;'</SAMP><DD> Append, including <SAMP>`stderr'</SAMP><DT><SAMP>`&#62;&#62;!'</SAMP><DD>Append, ignoring <SAMP>`noclobber'</SAMP><DT><SAMP>`&#62;&#62;&#38;!'</SAMP><DD>Append <SAMP>`stdout'</SAMP>, <SAMP>`stderr'</SAMP>, ignore <SAMP>`noclobber'</SAMP><DT><SAMP>`&#60;&#60;'</SAMP><DD>See below.</DL><P>The last of these commands reads from the standard input until itfinds a line which contains a word. It then feeds all of this inputinto the program concerned. For example,<PRE>nexus% mail mark &#60;&#60;quitnexus 1&#62; Hello marknexus 2&#62; Nothing much to say...nexus 2&#62; so byenexus 2&#62; nexus 2&#62; quitSending mail...Mail sent!</PRE><P>The mail message contains all the lines up to, but not including `marker'.This method can also be used to print text verbatim from a filewithout using multiple echo commands. Inside a script onemay write:<A NAME="IDX610"></A><A NAME="IDX611"></A></P><PRE>cat &#60;&#60; "marker";           MENU    1) choice 1    2) choice 2    ...marker</PRE><P>The <CODE>cat</CODE> command writes directly to <CODE>stdout</CODE> and theinput is redirected and taken directly from the script file.<A NAME="IDX612"></A><A NAME="IDX613"></A></P><P><A NAME="IDX614"></A><A NAME="IDX615"></A>A very useful construction is the `pipe' facility.  Using the <SAMP>`|'</SAMP>symbol one can feed the <SAMP>`stdout'</SAMP> of one program straight intothe <SAMP>`stdin'</SAMP> of another program. Similarly with <SAMP>`|&#38;'</SAMP> both<SAMP>`stdout'</SAMP> and <SAMP>`stderr'</SAMP> can be piped into the input of anotherprogram. This is very convenient. For instance, look up the followingcommands in the manual and try them.</P><P><A NAME="IDX616"></A><PRE>ps aux | moreecho 'Keep on sharpening them there knives!' | mail henryvmstat 1 | headls -l /etc | tail</PRE><P>Note that when piping both standard input and standard error to anotherprogram, the two files <EM>do not mix synchronously</EM>. Often <SAMP>`stderr'</SAMP>appears first.</P><H2><A NAME="SEC97" HREF="unix_toc.html#TOC97"><SAMP>`tee'</SAMP> and <SAMP>`script'</SAMP></A></H2><P><A NAME="IDX617"></A><A NAME="IDX618"></A><A NAME="IDX619"></A><A NAME="IDX620"></A>Occasionally you might want to have a copy of what you see on yourterminal sent to a file. <SAMP>`tee'</SAMP> and <SAMP>`script'</SAMP> do this. Forinstance,<PRE>find / -type l  -print | tee myfile</PRE><P>sends a copy of the output of <SAMP>`find'</SAMP> to the file `myfile'. <SAMP>`tee'</SAMP>can split the output into as many files as you want:</P><PRE><VAR>command</VAR> | tee <VAR>file1</VAR> <VAR>file2</VAR> ....</PRE><P>You can also choose to record the output an entire shell session usingthe <SAMP>`script'</SAMP> command.<PRE>nexus% script mysessionScript started, file is mysessionnexus% echo Big brother is scripting youBig brother is scripting younexus% exitexitScript done, file is mysession</PRE><P>The file `mysession' is a text file which contains a transcript of thesession.</P><H2><A NAME="SEC98" HREF="unix_toc.html#TOC98">Scripts with arguments</A></H2><P><A NAME="IDX621"></A><A NAME="IDX622"></A><A NAME="IDX623"></A></P><P>One of the useful features of the shell is that you can use the normalUNIX commands to make programs called <EM>scripts</EM>. To make a script,you just create a file containing shell commands you want to execute andmake sure that the first line of the file looks like the following example.</P><PRE>#!/bin/csh -f## A simple script: check for user's mail##set path = ( /bin /usr/ucb )               # Set the local pathcd /var/spool/mail                         # Change dirforeach uid ( * )   echo "$uid has mail in the intray! "    # space prevents an error!end</PRE><P><A NAME="IDX624"></A>The sequence <SAMP>`#!/bin/csh'</SAMP> means that the following commands are tobe fed into <TT>`/bin/csh'</TT>. The two symbols <SAMP>`#!'</SAMP> must be the veryfirst two characters in the file.  The <SAMP>`-f'</SAMP> option means that your<SAMP>`.cshrc'</SAMP> file is not read by the shell when it starts up.  The filecontaining this script must be executable (see <SAMP>`chmod'</SAMP>) and must bein the current path, like all other programs.</P><P><A NAME="IDX625"></A><A NAME="IDX626"></A><A NAME="IDX627"></A><A NAME="IDX628"></A>Like C programs, C-shell scripts can accept command line arguments.Suppose you want to make a program to say hello to some otherusers who are logged onto the system.<PRE>say-hello mark sarah mel </PRE><P>To do this you need to know the names that were typed on the commandline. These names are copied into an array in the C-shell calledthe <EM>argument vector</EM>, or <SAMP>`argv'</SAMP>. To read these arguments,you just treat <SAMP>`argv'</SAMP> as an array.</P><P><A NAME="IDX629"></A><A NAME="IDX630"></A><PRE>#!/bin/csh -f## Say hello#foreach name ( $argv )   echo Saying hello to $name   echo "Hello from $user! " | write $nameend</PRE><P>The elements of the array can be referred to as <SAMP>`argv[1]'</SAMP>..<SAMP>`argv[$#argv]'</SAMP> as usual. They can also be referredto as <SAMP>`$1'</SAMP>..<SAMP>`$3'</SAMP> up to the last acceptable number. This makesC-shell compatible with the Bourne shell as far as arguments areconcerned. One extra flourish in this method is that you can alsorefer to the name of the program itself as <SAMP>`$0'</SAMP>.For example,<PRE>#!/bin/csh -fecho This is program $0 running for $user</PRE><P><SAMP>`$argv'</SAMP> represents all the arguments. You can also use<SAMP>`$*'</SAMP> from the Bourne shell.</P><H2><A NAME="SEC99" HREF="unix_toc.html#TOC99">Sub-shells ()</A></H2><P><A NAME="IDX631"></A><A NAME="IDX632"></A></P><P>The C-shell does not allow you to define subroutines or functions, butyou can create a local shell, with its own private variables byenclosing commands in parentheses.<PRE>#!/bin/cshcd /etc( cd /usr/bin; ls * ) &#62; myfilepwd</PRE><P>This program changes the working directory to /etc and then executesa subshell which <EM>inside the brackets</EM> changes directory to/usr/bin and lists the files there. The output of this privateshell are sent to a file `myfile'. At the end we print out thecurrent working directory just to show that the <SAMP>`cd'</SAMP> commandin brackets had no effect on the main program.</P><P>Normally both parentheses must be on the same line.If a subshell command line gets too long, so that the brackets are noton the same line, you have to use backslash characters to continue thelines,<PRE>(  command \   command \   command \)<A NAME="IDX633"></A><A NAME="IDX634"></A></PRE><P> <H2><A NAME="SEC100" HREF="unix_toc.html#TOC100">Tests and conditions</A></H2><P><A NAME="IDX635"></A><A NAME="IDX636"></A></P><P>No programming language would be complete without tests and loops.C-shell has two kinds of decision structure: the <SAMP>`if..then..else'</SAMP>and the <SAMP>`switch'</SAMP> structure. These are closely related to theirC counterparts. The syntax of these is<PRE>if (<VAR>condition</VAR>) <VAR>command</VAR>if (<VAR>condition</VAR>) then   command   command..else   command   command..endif<A NAME="IDX637"></A>switch (<VAR>string</VAR>)  case <VAR>one</VAR>:               commands              breaksw  case <VAR>two</VAR>:               commands              breaksw  ...endsw</PRE><P>In the latter case, no commands should appear on the same line as a `case'statement, or they will be ignored. Also, if the <SAMP>`breaksw'</SAMP>commands are omitted, then control flows through all the commandsfor case 2, case 3 etc, exactly as it does in the C programminglanguage.</P><P>We shall consider some examplesof these statements in a moment, but first it is worth listing someimportant tests which can be used in <SAMP>`if'</SAMP> questions to findout information about files.<A NAME="IDX638"></A><A NAME="IDX639"></A><A NAME="IDX640"></A><A NAME="IDX641"></A><A NAME="IDX642"></A><A NAME="IDX643"></A><A NAME="IDX644"></A></P><DL COMPACT><DT><SAMP>`-r <VAR>file</VAR>'</SAMP><DD>True if the file exists and is readable<DT><SAMP>`-w <VAR>file</VAR>'</SAMP><DD>True if the file exists and is writable<DT><SAMP>`-x <VAR>file</VAR>'</SAMP><DD>True if the file exists and is executable<DT><SAMP>`-e <VAR>file</VAR>'</SAMP><DD>True if the file simply exists<DT><SAMP>`-z <VAR>file</VAR>'</SAMP><DD>True if the file exists and is empty<DT><SAMP>`-f <VAR>file</VAR>'</SAMP><DD>True if the file is a plain file<DT><SAMP>`-d <VAR>file</VAR>'</SAMP><DD>True if the file is a directory</DL><P>We shall also have need of the following comparison operators.</P><P><A NAME="IDX645"></A><A NAME="IDX646"></A><A NAME="IDX647"></A><A NAME="IDX648"></A><A NAME="IDX649"></A><A NAME="IDX650"></A><A NAME="IDX651"></A><A NAME="IDX652"></A><A NAME="IDX653"></A><A NAME="IDX654"></A></P><DL COMPACT><DT><SAMP>`=='</SAMP><DD>is equal to (string comparison)<DT><SAMP>`!='</SAMP><DD>is not equal to<DT><SAMP>`&#62;'</SAMP><DD>is greater than<DT><SAMP>`&#60;'</SAMP><DD>is less than<DT><SAMP>`&#62;='</SAMP><DD>is greater than or equal to<DT><SAMP>`&#60;='</SAMP><DD>is less than or equal to<DT><SAMP>`=~'</SAMP><DD>matches a wildcard<DT><SAMP>`!~'</SAMP><DD>does not match a wildcard</DL><P>The simplest way to learn about these statements is to use them, so weshall now look at some examples.</P><PRE>#!/bin/csh -f##  Safe copy from &#60;arg[1]&#62; to &#60;arg[2]&#62;##if ($#argv != 2) then  echo "Syntax: copy &#60;from-file&#62; &#60;to-file&#62;"  exit 0endifif ( -f $argv[2] ) then   echo "File exists. Copy anyway?"   switch ( $&#60; )                     # Get a line from user      case y:               breaksw      default:               echo "Doing nothing!"               exit 0   endswendifecho -n "Copying $argv[1] to $argv[2]..."cp $argv[1] $argv[2]echo doneendif</PRE><P>This script tries to copy a file from one location to another. If theuser does not type exactly two arguments, the script quits with amessage about the correct syntax. Otherwise it tests to see whethera plain file has the same name as the file the user wanted to copyto. If such a file exists, it asks the user if he/she wants tocontinue before proceeding to copy.</P><H3><A NAME="SEC101" HREF="unix_toc.html#TOC101">Switch example: configure script</A></H3><P><A NAME="IDX655"></A><A NAME="IDX656"></A>Here is another example which compiles a software package.  This is a problem we shall return to later See section <A HREF="unix.html#SEC165">Make</A>. The problemthis script tries to address is the following. There are many differentversions of UNIX and they are not exactly compatible with oneanother. The program this file compiles has to work on any kind of UNIX,so it tries first to determine what kind of UNIX system the script isbeing run on by calling <SAMP>`uname'</SAMP>. Then it defines a variable<SAMP>`MAKE'</SAMP> which contains the path to the `make' program which willbuild <EM>software</EM>. The make program reads a file called `Makefile'which contains instructions for compiling the program, but this fileneeds to know the type of UNIX, so the script first copies a file`Makefile.src' using <SAMP>`sed'</SAMP> replace a dummy string with the realname of the UNIX. Then it calls make and sets the correct permission onthe file using <SAMP>`chmod'</SAMP>.<A NAME="IDX657"></A><A NAME="IDX658"></A></P><P><A NAME="IDX659"></A><A NAME="IDX660"></A><A NAME="IDX661"></A><PRE>#!/bin/csh -f#################################################### CONFIGURE Makefile AND BUILD software###################################################set NAME = ( `uname -r -s` )switch ($NAME[1])   case SunOS*:                  switch ($NAME[2])                     case 4*:                              setenv TYPE SUN4                              setenv MAKE /bin/make                              breaksw                     case 5*:                              setenv TYPE SOLARIS                              setenv MAKE /usr/ccs/bin/make                              breaksw                  endsw                  breaksw   case ULTRIX*:                  setenv TYPE ULTRIX                  setenv MAKE /bin/make                  breaksw   case HP-UX*:                  setenv TYPE HPUX                  setenv MAKE /bin/make                  breaksw   case AIX*:                  setenv TYPE AIX                  setenv MAKE /bin/make                  breaksw   case OSF*:                  setenv TYPE OSF                  setenv MAKE /bin/make                  breaksw   case IRIX*:                  setenv TYPE IRIX                  setenv MAKE /bin/make                  breaksw   default:                  echo Unknown architecture $NAME[1]endsw # Generate Makefile from source filesed s/HOSTTYPE/$TYPE/ Makefile.src &#62; Makefileecho "Making software. Type CTRL-C to abort and edit Makefile"$MAKE software         # call make to build programchmod 755 software     # set correct protection</PRE><P> <H2><A NAME="SEC102" HREF="unix_toc.html#TOC102">Loops in csh</A></H2><P><A NAME="IDX662"></A><A NAME="IDX663"></A><A NAME="IDX664"></A><A NAME="IDX665"></A><A NAME="IDX666"></A><A NAME="IDX667"></A><A NAME="IDX668"></A></P><P>The C-shell has three loop structures: <SAMP>`repeat'</SAMP>, <SAMP>`while'</SAMP>and <SAMP>`foreach'</SAMP>. We have already seen some examples of the <SAMP>`foreach'</SAMP>loop.</P><P>The structure of these loops is as follows<PRE>repeat <VAR>number-of-times</VAR> <VAR>command</VAR>while ( <VAR>test expression</VAR> )   <VAR>commands</VAR>endforeach  <VAR>control-variable</VAR>  ( <VAR>list-or-array</VAR> )   <VAR>commands</VAR>end</PRE><P><A NAME="IDX669"></A><A NAME="IDX670"></A>The commands <SAMP>`break'</SAMP> and <SAMP>`continue'</SAMP>can be used to break out of the loops at anytime. Here are some examples.</P><PRE>repeat 2 echo "Yo!" | write mark</PRE><P></P><P>This sends the message "Yo!" to mark's terminal twice.<PRE>repeat 5 echo `echo "Shutdown time! Log out now" | wall ; sleep 30` ; halt</PRE><P>This example repeats the command `echo Shutdown time...'five times at 30 second intervals, before shutting down the system.Only the superuser can run this command! Note the strangeconstruction with `echo echo'. This is to force the repeat commandto take two shell commands as an argument. (Try to explainwhy this works for yourself.)</P><P> <H2><A NAME="SEC103" HREF="unix_toc.html#TOC103">Input from the user</A></H2><P><A NAME="IDX671"></A><A NAME="IDX672"></A><A NAME="IDX673"></A><A NAME="IDX674"></A></P><PRE># Test a user responseecho "Answer y/n (yes or no)"set valid = falsewhile ( $valid == false )   switch ( $&#60; )      case y:               echo "You answered yes"              set valid = true              breaksw      case n:               echo "You answered no"              set valid = true              breaksw      default:              echo "Invalid response, try again"              breaksw   endswend</PRE><P>Notice that it would have been simpler to replace the two lines<PRE>  set valid = true  breaksw</PRE><P>by a single line <SAMP>`break'</SAMP>. <SAMP>`breaksw'</SAMP> jumps out of the switchconstruction, after which the <SAMP>`while'</SAMP> test fails. <SAMP>`break'</SAMP>jumps out of the entire while loop.</P><P> <H2><A NAME="SEC104" HREF="unix_toc.html#TOC104">Extracting parts of a pathname</A></H2><P><A NAME="IDX675"></A><A NAME="IDX676"></A><A NAME="IDX677"></A><A NAME="IDX678"></A><A NAME="IDX679"></A><A NAME="IDX680"></A></P><P>A path name consists of a number of different parts:<UL><LI>The path to the directory where a file is held.<LI>The name of the file itself.<LI>The file extension (after a dot).</UL><P>By using one of the following modifiers, we can extract thesedifferent elements.</P><DL COMPACT><DT><SAMP>`:h'</SAMP><DD>The path to the file <DT><SAMP>`:t'</SAMP><DD>The filename itself <DT><SAMP>`:e'</SAMP><DD>The file extension <DT><SAMP>`:r'</SAMP><DD>The complete file-path minus the file extension </DL><P>Here are some examples and the results:<PRE>set f = ~/progs/c++/test.Cecho $f:h     /home/mark/progs/c++echo $f:t      test.Cecho $f:e       Cecho $f:r       /home/mark/progs/c++/test</PRE><P></P><P> <H2><A NAME="SEC105" HREF="unix_toc.html#TOC105">Arithmetic</A></H2><P>Before using these features in a real script, we need one more possibility:numerical addition, subtraction and multiplication etc.</P><P><A NAME="IDX681"></A><A NAME="IDX682"></A><A NAME="IDX683"></A><A NAME="IDX684"></A><A NAME="IDX685"></A><A NAME="IDX686"></A><A NAME="IDX687"></A><A NAME="IDX688"></A><A NAME="IDX689"></A><A NAME="IDX690"></A><A NAME="IDX691"></A><A NAME="IDX692"></A><A NAME="IDX693"></A><A NAME="IDX694"></A><A NAME="IDX695"></A><A NAME="IDX696"></A><A NAME="IDX697"></A><A NAME="IDX698"></A></P><P>To tell the C-shell that you want to perform an operation on numbersrather than strings, you use the <SAMP>`@'</SAMP> symbol followed by a space.Then the following operations are possible.<PRE>@ var = 45                      # Assign a numerical value to varecho $var                       # Print the value@ var = $var + 34               # Add 34 to var@ var += 34                     # Add 34 to var@ var -= 1                      # subtract 1 from var@ var *= 5                      # Multiply var by 5@ var /= 3                      # Divide var by 3 (integer division)@ var %= 3                      # Remainder after dividing var by 3@ var++                         # Increment var by 1@ var--                         # Decrement var by 1@ array[1] = 5                  # Numerical array@ logic = ( $x &#62; 6 &#38;&#38; $x &#60; 10)  # AND@ logic = ( $x &#62; 6 || $x &#60; 10)  # OR@ false = ! $var                # Logical NOT@ bits = ( $x | $y )            # Bitwise OR @ bits = ( $x ^ $y )            # Bitwise XOR@ bits = ( $x &#38; $y )            # Bitwise AND@ shifted = ( $var &#62;&#62; 2 )       # Bitwise shift right@ back    = ( $var &#60;&#60; 2 )       # Bitwise shift left</PRE><P>These operators are precisely those found in the C programming language.</P><P> <H2><A NAME="SEC106" HREF="unix_toc.html#TOC106">Examples</A></H2><P>The following script uses the operators in the last two sectionsto take a list of files with a given file extension (say <SAMP>`.doc'</SAMP>)and change it for another (say <SAMP>`.tex'</SAMP>). This is a partialsolution to the limitation of not being able to do multiplerenames in shell.</P><PRE>#!/bin/csh -f############################################################### Change file extension for multiple files##############################################################if ($#argv &#60; 2) then  echo Syntax: chext oldpattern newextension  echo "e.g: chext *.doc tex "  exit 0endifmkdir /tmp/chext.$user                 # Make a scratch areaset newext="$argv[$#argv]"             # Last arg is new extset oldext="$argv[1]:e"echo "Old extension was ($oldext)""echo "New extension ($newext) -- okay? (y/n)"switch( $&#60; )   case y:           breaksw   default:            echo "Nothing done."           exit 0endsw############################################################### Remove the last file extension from files############################################################## i = 0foreach file ($argv)   i++  if ( $i == $#argv ) break  cp $file /tmp/chext.$user/$file:r        # temporary storeend################################################################ Add .newext file extension to files###############################################################set array = (`ls /tmp/chext.$user`)foreach file ($array)  if ( -f $file.$newext ) then    echo  destination file $file.$newext exists. No action taken.    continue  endif  cp /tmp/chext.$user/$file $file.$newext  rm $file.$oldextendrm -r /tmp/chext.$user</PRE><P>Here is another example to try to decipher. Use the manual pages tofind out about <SAMP>`awk'</SAMP>. This script can be written much moreeasily in Perl or C, as we shall see in the next chapters. It isalso trivially implemented as a script in the system administrationlanguage cfengine.</P><PRE>#!/bin/csh -f############################################################# KILL all processes owned by $argv[1] with PID &#62; $argv[2]############################################################<A NAME="IDX699"></A>if ("`whoami`" != "root") then  echo Permission denied  exit 0endifif ( $#argv &#60; 1 || $#argv &#62; 2 ) then  echo Usage: KILL username lowest-pid  exit 0endifif ( $argv[1] == "root") then  echo No! Too dangerous -- system will crash  exit 0endif############################################################# Kill everything############################################################if ( $#argv == 1 ) then  set killarray = ( `ps aux |  awk '{ if ($1 == user) \{printf "%s ",$2}}' user=$argv[1]` )  foreach process ($killarray)     kill -1 $process     kill -15 $process &#62; /dev/null     kill -9 $process &#62; /dev/null     if ("`kill -9 $process | egrep -e 'No such process'`" == "") then        echo "Warning - $process would not die - try again"     endif  end############################################################## Start from a certain PID#############################################################else if ( $#argv == 2 ) then  set killarray = ( `ps aux |  awk '{ if ($1 == user &#38;&#38; $2 &#62; uid) \{printf "%s ",$2}}' user=$argv[1] uid=$argv[2]` )  foreach process ($killarray)<A NAME="IDX700"></A>     kill -1 $process &#62; /dev/null     kill -15 $process     sleep 2     kill -9 $process &#62; /dev/null     if ("`kill -9 $process | egrep -e 'No such process'`" == "") then        echo "Warning - $process would not die - try again"     endif  endendif</PRE><P>This program would be better written in C or Perl.</P><P> <H2><A NAME="SEC107" HREF="unix_toc.html#TOC107">Summary: Limitations of shell programming</A></H2><P><A NAME="IDX701"></A></P><P>To summarize the last two long and oppressive chapters we shall take astep back from the details and look at what we have achieved.</P><P>The idea behind the shell is to provide a userinterface, with access to the system's facilities at a simple level.In the 70's user interfaces were not designed to be user-friendly.The UNIX shell is not particularly use friendly, but it is very powerful.Perhaps it would have been enough to provide only commands to allow usersto write C programs. Since all of the system functions areavailable from C, that would certainly allow everyone to do whatanything that UNIX can do. But shell programming is much more<EM>immediate</EM> than C. It is an environment of <EM>frequently used tools</EM>.Also for quick programming solutions: C is a compiled language, whereas theshell is an interpreter. A quick shell program can solve manyproblems in no time at all, without having to compile anything.</P><P>Shell programming is only useful for `quick and easy' programs. To useit for anything serious is an abuse.  Programming difficult things inshell is clumsy, and it is difficult to get returned-information (likeerror messages) back in a useful form. Besides, shell scripts areslow compared to real programs since they involve startinga new program for each new command.</P><P>These difficulties are solved partly by Perl, which we shall considernext -- but in the final analysis, real programs of substanceneed to be written in C. Contrary to popular belief, this isnot more difficult than programming in the shell -- in fact, manythings are much simpler, because all of the shell commands originatedas C functions. The shell is an extra layer of the UNIX onion whichwe have to battle our way through to get where we're going.</P><P>Sometimes it is helpful to be shielded from <EM>low level</EM> details-- sometimes it is a <EM>hindrance</EM>. In the remaining chapterswe shall consider more involved programming needs.</P><H1><A NAME="SEC108" HREF="unix_toc.html#TOC108">Perl</A></H1><P><A NAME="IDX702"></A>So far, we have been looking at shell programming for performingfairly simple tasks. Now let's extend the idea of shell programmingto cover more complex tasks like systems programming and networkcommunications. Perl is a language which was designed to retain theimmediateness of shell languages, but at the same time capture someof the flexibility of C. Perl is an acronym for <EM>Practical extractionand report language</EM>. In this chapter, we shall not aim to teach Perlfrom scratch -- the best way to learn it is to use it! Ratherwe shall concentrate on demonstrating some principles.</P><P> </P><H2><A NAME="SEC109" HREF="unix_toc.html#TOC109">Sed and awk, cut and paste</A></H2><P><A NAME="IDX703"></A><A NAME="IDX704"></A><A NAME="IDX705"></A><A NAME="IDX706"></A></P><P>One of the reasons for using Perl is that it is extremely good attextfile handling--one of the most important things for UNIX users, andparticularly useful in connection with CGI script processing on theWorld Wide Web.  It has simple built-in constructs for searching andreplacing text, storing information in arrays and retrieving them insorted form. All of the these things have previously been possible usingthe UNIX shell commands<PRE>sedawkcutpaste</PRE><P>but these commands were designed to work primarily in the Bourne shelland are a bit <SAMP>`awk'</SAMP>ward to use for all but the simplest applications.</P><DL COMPACT><DT><SAMP>`sed'</SAMP><DD>is a stream editor. It takes command line instructions, reads input fromthe stream <CODE>stdin</CODE> and produces output on <EM>stdout</EM> accordingto those instructions. <SAMP>`sed'</SAMP> works line by line from the start of atextfile.<DT><SAMP>`awk'</SAMP><DD>is a pattern matching and processing language. It takes a textfile andreads it line by line, matching <EM>regular expressions</EM> and acting onthem. <SAMP>`awk'</SAMP> is powerful enough to have conditional instructionslike <SAMP>`if..then..else'</SAMP> and uses C's <SAMP>`printf'</SAMP> construction foroutput.<DT><SAMP>`cut'</SAMP><DD>Takes a line of input and cuts it into <EM>fields</EM>,separated by some character. For instance, a normal line of text isa string of words separated by spaces. Each word is a different field. <SAMP>`cut'</SAMP> can be used, for instance, to pick out the third column in atable. Any character can be specified as the separator.<DT><SAMP>`paste'</SAMP><DD>is the logical opposite of cut. It concatenates @math{n}files, and makes each line in the file into a column of a table. For instance,<SAMP>`paste one two three'</SAMP> would make a table in which the firstcolumn consisted of all lines in <SAMP>`one'</SAMP>, the second of all linesin <SAMP>`two'</SAMP> and the third of all lines in <SAMP>`three'</SAMP>. If one fileis longer than the others, then some columns have blank spaces.</DL><P>Perl unifies all of these operations and more. It alsomakes them much simpler.</P><P> <H2><A NAME="SEC110" HREF="unix_toc.html#TOC110">Program structure</A></H2><P>To summarize Perl, we need to know about the structure of a Perlprogram, the conditional constructs it has, its loops and its variables.In the latest versions of Perl (Perl 5), you can write object orientedprograms of great complexity. We shall not go into this depth, for thesimple reason that Perl's strength is not as a general programminglanguage but as a specialized language for textfile handling.  Thesyntax of Perl is in many ways like the C programming language, butthere are important differences.</P><UL><LI>Variables do not have <EM>types</EM>. They are interpretedin a context sensitive way. The operators which acts upon variablesdetermine whether a variable is to be considered a string or as an integer etc.<A NAME="IDX707"></A><A NAME="IDX708"></A><LI>Although there are no types, Perl defines <EM>arrays</EM> ofdifferent kinds. There are three different kinds of array, labelled by thesymbols <SAMP>`$'</SAMP>, <SAMP>`@'</SAMP>  and <SAMP>`%'</SAMP>.<A NAME="IDX709"></A><LI>Perl keeps a number of standard variables with special namese.g. <SAMP>`$_ @ARGV'</SAMP> and <SAMP>`%ENV'</SAMP>. Special attention should be paidto these. They are very important!<A NAME="IDX710"></A><A NAME="IDX711"></A><A NAME="IDX712"></A><LI>The shell reverseapostrophe notation <CODE>`command`</CODE> can be used to execute UNIXprograms and get the result into a Perl variable.<A NAME="IDX713"></A></UL><P>Here is a simple `structured hello world' program in Perl. Noticethat subroutines are called using the <SAMP>`&#38;'</SAMP> symbol. There isno special way of marking the main program -- it is simplythat part of the program which starts at line 1.</P><PRE>#!/local/bin/perl## Comments#&#38;Hello();&#38;World;# end of mainsub Hello   {   print "Hello";   }sub World   {   print "World\n";   }</PRE><P>The parentheses on subroutines are optional, if there are no parameters passed.Notice that each line must end in a semi-colon.</P><P> <H2><A NAME="SEC111" HREF="unix_toc.html#TOC111">Perl variables</A></H2><P> </P><H3><A NAME="SEC112" HREF="unix_toc.html#TOC112">Scalar variables</A></H3><P><A NAME="IDX714"></A><A NAME="IDX715"></A><A NAME="IDX716"></A></P><P>In Perl, variables do not have to be declared before they are used.Whenever you use a new symbol, Perl automatically adds the symbol toits symbol table and initializes the variable to the emptystring.</P><P>It is important to understand that there is no practical difference between zero and the empty string in perl -- except in the way that you, the user, choose touse it. Perl makes no distinction between strings and integers or any othertypes of data -- except when it wants to interpret them. For instance,to compare two variables as strings is not the same as comparing themas integers, even if the string contains a textual representation of aninteger. Take a look at the following program.</P><PRE>#!/local/bin/perl## Nothing!#print "Nothing == $nothing\n";print "Nothing is zero!\n" if ($nothing == 0);if ($nothing eq "")   {   print STDERR "Nothing is really nothing!\n";   }$nothing = 0;print "Nothing is now $nothing\n";</PRE><P>The output from this program is</P><PRE>Nothing == Nothing is zero!Nothing is really nothing!Nothing is now 0</PRE><P><A NAME="IDX717"></A></P><P>There are several important things to note here. First of all, we neverdeclare the variable `nothing'.  When we try to write its value, perlcreates the name and associates a NULL value to it i.e. the emptystring. There is no error. Perl knows it is a variable because of the<SAMP>`$'</SAMP> symbol in front of it. All <EM>scalar</EM> variables areidentified by using the dollar symbol.</P><P><A NAME="IDX718"></A><A NAME="IDX719"></A><A NAME="IDX720"></A></P><P>Next, we compare the value of <SAMP>`$nothing'</SAMP> to the integer `0' usingthe integer comparison symbol <SAMP>`=='</SAMP>, and then we compare it to theempty string using the string comparison symbol <SAMP>`eq'</SAMP>.  Both testsare true! That means that the empty string is interpreted as having anumerical value of zero. In fact <EM>any string</EM> which does not form avalid integer number has a numerical value of zero.</P><P>Finally we can set <SAMP>`$nothing'</SAMP> explicitly to a valid integerstring zero, which would now pass the first test, but fail thesecond.</P><P>As extra spice, this program also demonstrates two different waysof writing the <SAMP>`if'</SAMP> command in perl.</P><P> <H3><A NAME="SEC113" HREF="unix_toc.html#TOC113">The default scalar variable.</A></H3><P>The special variable <SAMP>`$_'</SAMP> is used for many purposes in Perl.It is used as a buffer to contain the result of the last operation,the last line read in from a file etc. It is so general that manyfunctions which act on scalar variables work by default on <SAMP>`$_'</SAMP>if no other argument is specified. For example,<PRE>print;</PRE><P>is the same as<PRE>print $_;</PRE><P> <H3><A NAME="SEC114" HREF="unix_toc.html#TOC114">Array (vector) variables</A></H3><P><A NAME="IDX721"></A>The complement of scalar variables is arrays. An array, in Perl isidentified by the <SAMP>`@'</SAMP> symbol and, like scalar variables, isallocated and initialized dynamically.<PRE>@array[0] = "This little piggy went to market";@array[2] = "This little piggy stayed at home";print "@array[0] @array[1] @array[2]";</PRE><P>The index of an array is always understood to be a number, nota string, so if you use a non-numerical string to refer to an arrayelement, you will always get the zeroth element, since a non-numericalstring has an integer value of zero.</P><P>An important array which every program defines is<PRE>@ARGV</PRE><P>This is the argument vector array, and contains the commands line argumentsby analogy with the C-shell variable <SAMP>`$argv[]'</SAMP>.</P><P>Given an array, we can find the last element by using the <SAMP>`$#'</SAMP>operator. For example,<PRE>$last_element = $ARGV[$#ARGV];</PRE><P>Notice that each element in an array is a scalar variable. The <SAMP>`$#'</SAMP>cannot be interpreted directly as the number of elements in the array,as it can in the C-shell. You should experiment with the value of thisquantity -- it often necessary to add 1 or 2 to its value in order toget the behaviour one is used to in the C-shell.</P><P>Perl does not support multiple-dimension arrays directly, but it ispossible to simulate them yourself. (See the Perl book.)</P><P><A NAME="IDX722"></A><A NAME="IDX723"></A></P><P> <H3><A NAME="SEC115" HREF="unix_toc.html#TOC115">Special array commands</A></H3><P>The <SAMP>`shift'</SAMP> command acts on arrays and returns and removes thefirst element of the array. Afterwards, all of the elements are shifteddown one place. So one way to read the elements of an array in order isto repeatedly call <SAMP>`shift'</SAMP>.</P><PRE>$next_element=shift(@myarray);</PRE><P><A NAME="IDX724"></A><A NAME="IDX725"></A>Note that, if the array argument is omitted, then <SAMP>`shift'</SAMP>works on <SAMP>`@ARGV'</SAMP> by default.</P><P><A NAME="IDX726"></A><A NAME="IDX727"></A><A NAME="IDX728"></A>Another useful function is <SAMP>`split'</SAMP>, which takes a string and turnsit into an array of strings. <SAMP>`split'</SAMP> works by choosing a character(usually a space) to delimit the array elements, so a string containinga sentence separated by spaces would be turned into an array ofwords. The syntax is</P><PRE>@array = split;                       # works with spaces on $_@array = split(pattern,string);       # Breaks on pattern($v1,$v2...) = split(pattern,string); # Name array elements with scalars</PRE><P>In the first of these cases, it is assumed that the variable <SAMP>`$_'</SAMP>is to be split on whitespace characters. In the second case, we decideon what character the split is to take place and on what string thefunction is to act. For instance</P><PRE>@new_array = split(":","name:passwd:uid:gid:gcos:home:shell");</PRE><P>The result is a seven element array called <SAMP>`@new_array'</SAMP>, where<SAMP>`$new_array[0]'</SAMP> is <SAMP>`name'</SAMP> etc.</P><P>In the final example, the left hand side shows that we wish to captureelements of the array in a named set of scalar variables.  If thenumber of variables on the lefthand side is fewer than the number ofstrings which are generated on the right hand side, they arediscarded. If the number on the left hand side is greater, then theremainder variables are empty.</P><P> <H3><A NAME="SEC116" HREF="unix_toc.html#TOC116">Associated arrays</A></H3><P><A NAME="IDX729"></A>One of the very nice features of Perl is the ability to use one stringas an index to another string in an array. For example, we can make ashort encyclopedia of zoo animals by constructing an associative arrayin which the keys (or indices) of the array are the names of animals, andthe contents of the array are the information about them.</P><PRE>$animals{"Penguin"} = "A suspicious animal, good with cheese crackers...";$animals{"dog"} = "Plays stupid, but could be a cover...";if ($index eq "fish")   {    $animals{$index} = "Often comes in square boxes. Very cold.";   }</PRE><P>An entire associated array is written <SAMP>`%array'</SAMP>, while the elementsare <SAMP>`$array{$key}'</SAMP>.</P><P>Perl provides a special associative array for every program called <SAMP>`%ENV'</SAMP>.This contains the <EM>environment variables</EM> defined in the parentshell which is running the Perl program. For example<PRE>print "Username = $ENV{"USER"}\n";$ld = "LD_LIBRARY_PATH";print "The link editor path is $ENV{$ld}\n";</PRE><P><A NAME="IDX730"></A>To get the current path into an ordinary array, one could write,<PRE>@path_array= split(":",$ENV{"PATH"});</PRE><P> <H3><A NAME="SEC117" HREF="unix_toc.html#TOC117">Array example program</A></H3><P>Here is an example which prints out a list of files in a specifieddirectory, in order of their UNIX protection bits. The <EM>least</EM>protected file files come first.</P><PRE>#!/local/bin/perl## Demonstration of arrays and associated arrays.# Print out a list of files, sorted by protection,# so that the least secure files come first.## e.g.     arrays &#60;list of words&#62;#          arrays *.C#############################################################print "You typed in ",$#ARGV+1," arguments to command\n";if ($#ARGV &#60; 1)     {   print "That's not enough to do anything with!\n";   }while ($next_arg = shift(@ARGV))      {   if ( ! ( -f $next_arg || -d $next_arg))      {      print "No such file: $next_arg\n";      next;      }   ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size) = stat($next_arg);   $octalmode = sprintf("%o",$mode &#38; 0777);   $assoc_array{$octalmode} .= $next_arg.            " : size (".$size."), mode (".$octalmode.")\n";   }print "In order: LEAST secure first!\n\n";foreach $i (reverse sort keys(%assoc_array))   {   print $assoc_array{$i};   }</PRE><P> <H2><A NAME="SEC118" HREF="unix_toc.html#TOC118">Loops and conditionals</A></H2><P><A NAME="IDX731"></A><A NAME="IDX732"></A><A NAME="IDX733"></A>Here are some of the most commonly used decision-makingconstructions and loops in Perl. The following is not acomprehensive list -- for that, you will have to lookin the Perl bible: <EM>Programming Perl</EM>, by Larry Walland Randal Schwartz. The basic pattern follows the Cprogramming language quite closely. In thecase of the <SAMP>`for'</SAMP> loop, Perl has both the C-likeversion, called <SAMP>`for'</SAMP> and a <SAMP>`foreach'</SAMP> commandwhich is like the C-shell implementation.</P><P><A NAME="IDX734"></A><A NAME="IDX735"></A><A NAME="IDX736"></A><A NAME="IDX737"></A><PRE>if (<VAR>expression</VAR>)   {   block;   }else   {   block;   }command if (<VAR>expression</VAR>);unless (<VAR>expression</VAR>)   {   block;   }else   {   block;   }while (<VAR>expression</VAR>)   {   block;   }do   {   block;   }while (<VAR>expression</VAR>);for (<VAR>initializer</VAR>; <VAR>expression</VAR>; <VAR>statement</VAR>)   {   block;   }foreach <VAR>variable</VAR>(<VAR>array</VAR>)   {   block;   }</PRE><P>In all cases, the <SAMP>`else'</SAMP> clauses may be omitted.</P><P>Strangely, perl does not have a <SAMP>`switch'</SAMP> statement, but the Perl bookdescribes how to make one using the features provided.</P><P>  </P><H3><A NAME="SEC119" HREF="unix_toc.html#TOC119">The for loop</A></H3><P>The for loop is exactly like that in C or C++ and is usedto iterate over a numerical index, like this:</P><PRE>for ($i = 0; $i &#60; 10; $i++)   {   print $i, "\n";   }</PRE><P><A NAME="IDX738"></A></P><P> <H3><A NAME="SEC120" HREF="unix_toc.html#TOC120">The foreach loop</A></H3><P>The foreach loop is like its counterpart in the C shell. Itis used for reading elements one by one from a regular array.For example,</P><PRE>foreach $i ( @array )   {   print $i, "\n";   }</PRE><P><A NAME="IDX739"></A></P><P> <H3><A NAME="SEC121" HREF="unix_toc.html#TOC121">Iterating over elements in arrays</A></H3><P>One of the main uses for <SAMP>`for'</SAMP> type loops is to iterateover successive values in an array. This can be done intwo ways which show the essential difference between<CODE>for</CODE> and <CODE>foreach</CODE>. </P><P>If we want to fetch each value in an array in turn, without caring aboutnumerical indices, the it is simplest to use the <CODE>foreach</CODE> loop.<A NAME="IDX740"></A></P><PRE> @array = split(" ","a b c d e f g"); foreach $var ( @array )    {    print $var, "\n";    }</PRE><P>This example prints each letter on a separate line.If, on the other hand, we are interested in the index,for the purposes of some calculation, then the <CODE>for</CODE>loop is preferable.</P><PRE> @array = split(" ","a b c d e f g"); for ($i = 0; $i &#60;= $#array; $i++)    {    print $array[$i], "\n";    }</PRE><P>Notice that, unlike the for-loop idiom in C/C++, the limitis <SAMP>`$i &#60;= $#array'</SAMP>, i.e. `less than or equal to' ratherthan `less than'. This is because the <SAMP>`$#'</SAMP> operatordoes not return the number of elements in the array butrather the last element.</P><P>Associated arrays are slightly different, since they do notuse numerical keys. Instead they use a set of strings,like in a database, so that you can use one string to lookup another. In order to iterate over the values in the arraywe need to get a list of these strings. The <CODE>keys</CODE>command is used for this.<A NAME="IDX741"></A><A NAME="IDX742"></A></P><PRE> $assoc{"mark"} = "cool"; $assoc{"GNU"} = "brave"; $assoc{"zebra"} = "stripy"; foreach $var ( keys %assoc )    {    print "$var , $assoc{$var} \n";    }</PRE><P>The order of the keys is not defined in the above example,but you can choose to sort them alphabetically by writing</P><PRE> foreach $var ( sort keys %assoc )</PRE><P>instead.</P><P> <H3><A NAME="SEC122" HREF="unix_toc.html#TOC122">Iterating over lines in a file</A></H3><P>Since Perl is about file handling we are very interested inreading files. Unlike C and C++, perl likes to read filesline by line. The angle brackets are used for this, See section <A HREF="unix.html#SEC123">Files in perl</A>.Assuming that we have some file handle <SAMP>`&#60;file&#62;'</SAMP>, for instance<SAMP>`&#60;STDIN&#62;'</SAMP>, we can always read the file line by linewith a while-loop like this.</P><PRE> while ($line = &#60;file&#62;)    {    print $line;    }</PRE><P>Note that <CODE>$line</CODE> includes the end of line character on the endof each line. If you want to remove it, you should add a `chop'command:</P><PRE> while ($line = &#60;file&#62;)    {    chop $line;    print "line = ($line)\n";    }</PRE><P><A NAME="IDX743"></A><A NAME="IDX744"></A></P><P> <H2><A NAME="SEC123" HREF="unix_toc.html#TOC123">Files in perl</A></H2><P><A NAME="IDX745"></A><A NAME="IDX746"></A><A NAME="IDX747"></A><A NAME="IDX748"></A>Opening files is straightforward in Perl. Files must be openedand closed using -- wait for it -- the commands<SAMP>`open'</SAMP> and <SAMP>`close'</SAMP>. You should be careful toclose files after you have finished with them -- especiallyif you are writing <EM>to</EM> a file. Files are bufferedand often large parts of a file are not actually writtenuntil the <SAMP>`close'</SAMP> command is received.</P><P>Three files are, of course, always open for every program,namely <SAMP>`STDIN'</SAMP>, <SAMP>`STDOUT'</SAMP>and <SAMP>`STDERR'</SAMP>.</P><P>Formally, to open a file, we must obtain a file descriptoror file handle. This is done using <SAMP>`open'</SAMP>;</P><P><A NAME="IDX749"></A><A NAME="IDX750"></A><PRE>open (file_descrip,"Filename");</PRE><P>The angular brackets <SAMP>`&#60;..&#62;'</SAMP> are used to read from the file.For example,</P><PRE>$line = &#60;file_descrip&#62;;</PRE><P>reads one line from the file associated with <SAMP>`file_descrip'</SAMP>.</P><P>Let's look at some examples of filing opening.Here is how we can implement UNIX's <SAMP>`cut'</SAMP> and <SAMP>`paste'</SAMP>commands in perl:</P><P><A NAME="IDX751"></A><PRE>#!/local/bin/perl## Cut in perl# # Cut second columnwhile (&#60;&#62;)   {   @cut_array = split;   print "@cut_array[1]\n";   }</PRE><P>This is the simplest way to open a file. The empty filedescriptor <SAMP>`&#60;&#62;'</SAMP> tells perl to take the argument of thecommand as a filename and open that file for reading.This is really short for <SAMP>`while($_=&#60;STDIN&#62;)'</SAMP> with thestandard input redirected to the named file.</P><P><A NAME="IDX752"></A>The <SAMP>`paste'</SAMP>program can be written as follows:</P><PRE>#!/local/bin/perl## Paste in perl## Two files only, syntax : paste file 1file2#open (file1,"@ARGV[0]") || die "Can't open @ARGV[0]\n";open (file2,"@ARGV[1]") || die "Can't open @ARGV[1]\n";while (($line1 = &#60;file1&#62;) || ($line2 = &#60;file2&#62;))   {   chop $line1;   chop $line2;   print "$line1	$line2\n";    # tab character between   }</PRE><P>Here we see more formally how to read from two separatefiles at the same time. Notice that, by putting theread commands into the test-expression for the <SAMP>`while'</SAMP>loop, we are using the fact that <SAMP>`&#60;..&#62;'</SAMP> returnsa non-zero (true) value unless we have reached theend of the file.</P><P>To write and append to files, we use the shell redirection symbolsinside the <SAMP>`open'</SAMP> command.<PRE>open(fd,"&#62; filename");    # open file for writingopen(fd,"&#62;&#62; filename");   # open file for appending</PRE><P>We can also open a pipe from an arbitrary UNIX commandand receive the output of that command as our input:<PRE>open (fd,"/bin/ps aux | ");</PRE><P> </P><H3><A NAME="SEC124" HREF="unix_toc.html#TOC124">A simple perl program</A></H3><P>Let us now write the simplest perl program which illustratesthe way in which perl can save time. We shall write it in threedifferent ways to show what the short cuts mean. Let us implementthe <SAMP>`cat'</SAMP> command, which copies files to the standard output.The simplest way to write this is perl is the following:</P><PRE>#!/local/bin/perlwhile (&#60;&#62;)   {    print;   }</PRE><P>Here we have made heavy use of the many default assumptions which perlmakes. The program is simple, but difficult to understand fornovices. First of all we use the default file handle <CODE>&#60;&#62;</CODE> whichmeans, take one line of input from a default file.  This object returnstrue as long as it has not reached the end of the file, so this loopcontinues to read lines until it reaches the end of file.  The defaultfile is standard input, unless this script is invoked with a commandline argument, in which case the argument is treated as a filename andperl attempts to open the argument-filename for reading. The<CODE>print</CODE> statement has no argument telling it what to print, butperl takes this to mean: print the default variable <SAMP>`$_'</SAMP>.</P><P>We can therefore write this more explicitly as follows:</P><PRE>#!/local/bin/perlopen (HANDLE,"$ARGV[1]");while (&#60;HANDLE&#62;)   {    print $_;   }</PRE><P>Here we have simply filled in the assumptions explicitly.The command <SAMP>`&#60;HANDLE&#62;'</SAMP> now reads a single line from thenamed file-handle into the default variable <SAMP>`$_'</SAMP>.To make this program more general, we can eliminate the defaultsentirely.</P><PRE>#!/local/bin/perlopen (HANDLE,"$ARGV[1]");while ($line=&#60;HANDLE&#62;)   {    print $line;   }</PRE><P> <H3><A NAME="SEC125" HREF="unix_toc.html#TOC125">== and <SAMP>`eq'</SAMP></A></H3><P>Be careful to distinguish between the comparison operator for integers<SAMP>`=='</SAMP> and the corresponding operator for strings <SAMP>`eq'</SAMP>. Thesedo not work in each other's places so if you get the wrong comparisonoperator your program might not work and it is quite difficult tofind the error.</P><P> <H3><A NAME="SEC126" HREF="unix_toc.html#TOC126">chop</A></H3><P><A NAME="IDX753"></A><A NAME="IDX754"></A><A NAME="IDX755"></A></P><P>The command <SAMP>`chop'</SAMP> cuts off the last character of a string.This is useful for removing newline characters when readingfiles etc. The syntax is<PRE>chop;         # chop $_;chop $scalar; # remove last character in $scalar</PRE><P> <H2><A NAME="SEC127" HREF="unix_toc.html#TOC127">Perl subroutines</A></H2><P><A NAME="IDX756"></A></P><P>Subroutines are indicated, as in the example above, by the ampersand<SAMP>`&#38;'</SAMP> symbol. When parameters are passed to a Perl subroutine, theyare handed over as an array called <SAMP>`@_'</SAMP>. Which is analogousto the <SAMP>`$_'</SAMP> variable. Here is a simple example:</P><PRE>#!/local/bin/perl$a="silver";$b="gold";&#38;PrintArgs($a,$b);# end of mainsub PrintArgs   {   ($local_a,$local_b) = @_;   print "$local_a, $local_b\n";   }</PRE><P><A NAME="IDX757"></A><A NAME="IDX758"></A></P><P> <H2><A NAME="SEC128" HREF="unix_toc.html#TOC128">die - exit on error</A></H2><P><A NAME="IDX759"></A><A NAME="IDX760"></A><A NAME="IDX761"></A>When a program has to quit and give a message, the <SAMP>`die'</SAMP>command is normally used. If called without an argument,Perl generates its own message including a line number at whichthe error occurred. To include your own message,you write</P><PRE>die "My message....";</PRE><P>If the string is terminated with a <SAMP>`\n'</SAMP> newline character,the line number of the error is not printed, otherwise Perlappends the line number to your string.</P><P>When opening files, it is common to see the syntax:<PRE>open (filehandle,"Filename") || die "Can't open...";</PRE><P>The logical <SAMP>`OR'</SAMP> symbol is used, because <SAMP>`open'</SAMP>returns true if all goes well, in which case the righthand side is never evaluated. If <SAMP>`open'</SAMP> is false,then die is executed. You can decide for yourself whetheror not you think this is good programming style -- we mentionit here because it is common practice.</P><P> <H2><A NAME="SEC129" HREF="unix_toc.html#TOC129">The <CODE>stat()</CODE> idiom</A></H2><P>The UNIX library function <CODE>stat()</CODE> is used to find out informationabout a given file. This function is available both in C and in Perl.In perl, it returns an array of values. Usually we are interested inknowing the access permissions of a file. <CODE>stat()</CODE> is calledusing the syntax</P><PRE>@array = stat ("<VAR>filename</VAR>");</PRE><P>or alternatively, using a named array</P><PRE>($device,$inode,$mode) = stat("<VAR>filename</VAR>");</PRE><P>The value returned in the <VAR>mode</VAR> variable is a bit-pattern,See section <A HREF="unix.html#SEC62">Protection bits</A>. The most useful way of treating thesebit patterns is to use octal numbers to interpret their meaning.</P><P>To find out whether a file is readable or writable to a group ofusers, we use a programming idiom which is very common for dealingwith bit patterns: first we define a mask which zeroes out allof the bits in the mode string except those which we arespecifically interested in. This is done by defining a maskvalue in which the bits we want are set to 1 and all others areset to zero. Then we AND the mask with the mode string. If theresult is different from zero then we know that all of thebits were also set in the mode string.As in C, the bitwise AND operator in perl is called <SAMP>`&#38;'</SAMP>.</P><P>For example, to test whether a file is writable to other usersin the same group as the file, we would write the following.</P><PRE>$mask = 020;   # Leading 0 means octal number($device,$inode,$mode) = stat("<VAR>file</VAR>");if ($mode &#38; $mask)   {   print "File is writable by the group\n";   }</PRE><P>Here the 2 in the second octal number means "write", the fact thatit is the second octal number from the right means that it refersto "group". Thus the result of the if-test is only true if thatparticular bit is true. We shall see this idiom in action below.</P><P> <H2><A NAME="SEC130" HREF="unix_toc.html#TOC130">Perl example programs</A></H2><P> </P><H3><A NAME="SEC131" HREF="unix_toc.html#TOC131">The passwd program and <SAMP>`crypt()'</SAMP> function</A></H3><P>Here is a simple implementation of the UNIX <SAMP>`passwd'</SAMP>program in Perl.<A NAME="IDX762"></A><A NAME="IDX763"></A><A NAME="IDX764"></A><A NAME="IDX765"></A><A NAME="IDX766"></A></P><PRE>#!/local/bin/perl## A perl version of the passwd program.## Note - the real passwd program needs to be much more# secure than this one. This is just to demonstrate the# use of the crypt() function.##############################################################print "Changing passwd for $ENV{'USER'} on $ENV{'HOST'}\n";system 'stty','-echo';print "Old passwd: ";$oldpwd = &#60;STDIN&#62;;chop $oldpwd;($name,$coded_pwd,$uid,$gid,$x,$y,$z,$gcos,$home,$shell)                                  = getpwnam($ENV{"USER"});if (crypt($oldpwd,$coded_pwd) ne $coded_pwd)   {   print "\nPasswd incorrect\n";   exit (1);   }$oldpwd = "";                         # Destroy the evidence!print "\nNew passwd: ";$newpwd = &#60;STDIN&#62;;print "\nRepeat new passwd: ";$rnewpwd = &#60;STDIN&#62;;chop $newpwd;chop $rnewpwd;if ($newpwd ne $rnewpwd)   {   print "\n Incorrectly typed. Password unchanged.\n";   exit (1);   }<A NAME="IDX767"></A>$salt = rand();$new_coded_pwd = crypt($newpwd,$salt);print "\n\n$name:$new_coded_pwd:$uid:$gid:$gcos:$home:$shell\n";</PRE><P> <H3><A NAME="SEC132" HREF="unix_toc.html#TOC132">Example with <SAMP>`fork()'</SAMP></A></H3><P>The following example uses the <SAMP>`fork'</SAMP> function tostart a daemon which goes into the background and watches thesystem to which process is using the greatest amount ofCPU time each minute. A pipe is opened from the BSD <SAMP>`ps'</SAMP>command.<A NAME="IDX768"></A><A NAME="IDX769"></A></P><PRE>#!/local/bin/perl## A fork() demo. This program will sit in the background and# make a list of the process which uses the maximum CPU average# at 1 minute intervals. On a quiet BSD like system this will# normally be the swapper (long term scheduler).#$true = 1;$logfile="perl.cpu.logfile";print "Max CPU logfile, forking daemon...\n";if (fork())   {   exit(0);   } while ($true)    {   open (logfile,"&#62;&#62; $logfile") || die "Can't open $logfile\n";   open (ps,"/bin/ps aux |") || die "Couldn't open a pipe from ps !!\n";   $skip_first_line = &#60;ps&#62;;   $max_process = &#60;ps&#62;;   close(ps);   print logfile $max_process;   close(logfile);   sleep 60;   ($a,$b,$c,$d,$e,$f,$g,$size) = stat($logfile);   if ($size &#62; 500)      {      print STDERR "Log file getting big, better quit!\n";      exit(0);      }   }</PRE><P> <H3><A NAME="SEC133" HREF="unix_toc.html#TOC133">Example reading databases</A></H3><P><A NAME="IDX770"></A><A NAME="IDX771"></A></P><P>Here is an example program with several of the above featuresdemonstrated simultaneously. This following program listsall users who have home directories on the current host.If the home area has sub-directories, corresponding togroups, then this is specified on the command line. Theword `home' causes the program to print out the homedirectories of the users.</P><PRE>#!/local/bin/perl#################################################################### allusers - list all users on named host, i.e. all#            users who can log into this machine. ## Syntax: allusers group#         allusers mygroup home#         allusers myhost group home## NOTE : This command returns only users who are registered on#        the current host. It will not find users which cannot#        be validated in the passwd file, or in the named groups#        in NIS. It assumes that the users belonging to#        different groups are saved in subdirectories of#        /home/hostname.###################################################################&#38;arguments();die "\n" if ( ! -d "/home/$server" );$disks = `/bin/ls -d /home/$server/$group`;foreach $home (split(/\s/,$disks))   {   open (LS,"cd $home; /bin/ls $home |") || die "allusers: Pipe didn't open";   while (&#60;LS&#62;)      {      $exists = "";      ($user) = split;      ($exists,$pw,$uid,$gid,$qu,$cm,$gcos,$dir)=getpwnam($user);      if ($exists)         {         if ($printhomes)            {            print "$dir\n";            }         else            {            print "$user\n";            }         }      }   close(LS);   }########################################################sub arguments   {   $printhomes = 0;   $group = "*";   $server = `/bin/hostname`;   chop $server;   foreach $arg (@ARGV)      {      if (substr($arg,0,1) eq "u")         {         $group = $arg;         next;         }      if ($arg eq "home")         {         $printhomes = 1;         next;         }      $server= $arg;     #default is to interpret as a server.      }   }</PRE><P> <H2><A NAME="SEC134" HREF="unix_toc.html#TOC134">Pattern matching and extraction</A></H2><P>Perl has regular expression operators for identifying patterns. Theoperator<PRE>     /<VAR>regular expression</VAR>/ </PRE><P>returns true of false depending on whether the regular expression matches thecontents of <CODE>$_</CODE>. For example</P><PRE>  if (/perl/)     {     print "String contains perl as a substring";     }  if (/(Sat|Sun)day/)     {     print "Weekend day....";     }</PRE><P>The effect is rather like the <CODE>grep</CODE> command.To use this operator on other variables you would write:<PRE>  $variable =~ /<VAR>regexp</VAR>/</PRE><P>Regular expression can contain parenthetic sub-expressions, e.g.<PRE>  if (/(Sat|Sun)day (..)th (.*)/)     {     $first = $1;     $second = $2;     $third = $3;     }</PRE><P>in which case perl places the objects matched by such sub-expressionsin the variables <CODE>$1</CODE>, <CODE>$2</CODE> etc.</P><P> <H2><A NAME="SEC135" HREF="unix_toc.html#TOC135">Searching and replacing text</A></H2><P><A NAME="IDX772"></A><A NAME="IDX773"></A><A NAME="IDX774"></A>The <SAMP>`sed'</SAMP>-like function for replacing all occurances of a stringis easily implemented in Perl using</P><PRE>while (&#60;input&#62;)   {   s/$search/$replace/g;   print output;   }</PRE><P>This example replaces the string inside the default variable. To replacein a general variable we use the operator <SAMP>`=~'</SAMP>, with syntax:</P><PRE>$variable =~ s/<VAR>search</VAR>/<VAR>replace</VAR>/</PRE><P>Here is an example of some of this operator in use. The following is aprogram which searches and replaces a string in several files.  This isuseful program indeed for making a change globally in a group of files!The program is called `file-replace'.</P><PRE>#!/local/bin/perl################################################################ Look through files for findstring and change to newstring# in all files.################################################################# Define a temporary file and check it doesn't exist#$outputfile = "tmpmarkfind";unlink $outputfile;## Check command line for list of files#if ($#ARGV &#60; 0)   {   die "Syntax: file-replace [file list]\n";   }print "Enter the string you want to find (Don't use quotes):\n\n:";$findstring=&#60;STDIN&#62;;chop $findstring;print "Enter the string you want to replace with (Don't use quotes):\n\n:";$replacestring=&#60;STDIN&#62;;chop $replacestring;#print "\nFind: $findstring\n";print "Replace: $replacestring\n";print "\nConfirm (y/n)  ";$y = &#60;STDIN&#62;;chop $y;if ( $y ne "y")   {   die "Aborted -- nothing done.\n";   }else   {   print "Use CTRL-C to interrupt...\n";   }## Now shift default array @ARGV to get arguments 1 by 1#while ($file = shift)         {   if ($file eq "file-replace")      {      print "Findmark will not operate on itself!";      next;      }   #   # Save existing mode of file for later   #   ($dev,$ino,$mode)=stat($file);   open (INPUT,$file) || warn "Couldn't open $file\n";   open (OUTPUT,"&#62; $outputfile") || warn "Can't open tmp";   $notify = 1;   while (&#60;INPUT&#62;)      {      if (/$findstring/ &#38;&#38; $notify)         {         print "Fixing $file...\n";         $notify = 0;         }      s/$findstring/$replacestring/g;<A NAME="IDX775"></A>      print OUTPUT;      }   close (OUTPUT);   #   # If nothing went wrong (if outfile not empty)   # move temp file to original and reset the   # file mode saved above   #<A NAME="IDX776"></A>   if (! -z $outputfile)      {      rename ($outputfile,$file);<A NAME="IDX777"></A>      chmod ($mode,$file);      }   else      {      print "Warning: file empty!\n.";      }   }</PRE><P>Similarly we can search for lines containing a string. Here isthe grep program written in perl</P><PRE>#!/local/bin/perl## grep as a perl program## Check arguments etcwhile (&#60;&#62;)   {   print if (/$ARGV[1]/);   }</PRE><P>The operator <SAMP>`/<VAR>search-string</VAR>/'</SAMP> returns true if the searchstring is a substring of the default variable <CODE>$_</CODE>. To searchan arbitrary string, we write<PRE> .... if (<VAR>teststring</VAR> =~ /<VAR>search-string</VAR>/);</PRE><P>Here <VAR>teststring</VAR> is searched for occurrances of <VAR>search-string</VAR>and the result is true if one is found.<A NAME="IDX778"></A></P><P>In perl you can use regular expressions to search for text patterns.Note however that, like all regular expression dialects, perl hasits own conventions. For example the dollar sign does not mean"match the end of line" in perl, instead one uses the <SAMP>`\n'</SAMP> symbol.Here is an example program which illustrates the use of regular expressionsin perl:</P><PRE>#!/local/bin/perl## Test regular expressions in perl## NB - careful with \ $ * symbols etc. Use " quotes since#      the shell interprets these!#open (FILE,"regex_test");$regex = $ARGV[$#ARGV];print "Looking for $ARGV[$#ARGV] in file...\n";while (&#60;FILE&#62;)   {   if (/$regex/)      {      print;      }   }## Test like this:##  regex '.*'       - prints every line (matches everything)#  regex '.'        - all lines except those containing only blanks #                     (. doesn't match ws/white-space)#  regex '[a-z]'    - matches any line containing lowercase#  regex '[^a-z]'   - matches any line containg something which is #                     not lowercase a-z#  regex '[A-Za-z]' - matches any line containing letters of any kind#  regex '[0-9]'    - match any line containing numbers#  regex '#.*'      - line containing a hash symbol followed by anything#  regex '^#.*'     - line starting with hash symbol (first char)#  regex ';\n'      - match line ending in a semi-colon#</PRE><P>Try running this program with the test data on the following filewhich is called <TT>`regex_test'</TT> in the example program.</P><PRE># A line beginning with a hash symbolJUST UPPERCASE LETTERSjust lowercase lettersLetters and numbers 123456123456A line ending with a semi-colon;Line with a comment # COMMENT...</PRE><P> <H2><A NAME="SEC136" HREF="unix_toc.html#TOC136">Example: convert mail to WWW pages</A></H2><P>Here is an example program which you could use to automaticallyturn a mail message of the form</P><PRE>From: NewswireTo: Mail2htmlSubject: Nothing happenedOn the 13th February at kl. 09:30 nothing happened. No footprintswere found leading to the scene of a terrible murder, no evidenceof a struggle .... etc etc</PRE><P>into an html-file for the world wide web. The program worksby extracting the message body and subject from the mailand writing html-commands around these to make a web page.The subject field of the mail becomes the title. The other headersget skipped, since the script searches for lines containing thesequence "colon-space" or <SAMP>`: '</SAMP>. A regular expressionis used for this.</P><PRE>#!/local/bin/perl## Make HTML from mail#&#38;BeginWebPage();&#38;ReadNewMail();&#38;EndWebPage();##########################################################sub BeginWebPage{    print "&#60;HTML&#62;\n";    print "&#60;BODY&#62;\n";}##########################################################sub EndWebPage{    print "&#60;/BODY&#62;\n";    print "&#60;/HTML&#62;\n";}##########################################################sub ReadNewMail{while (&#60;&#62;)   {   if (/Subject:/)   # Search for subject line      {      # Extract subject text...      chop;      ($left,$right) = split(":",$_);      print "&#60;H1&#62; $right &#60;/H1&#62;\n";      next;      }   elsif (/.*: .*/)   # Search for - anything: anything      {      next;           # skip other headers      }   print;   } }</PRE><P> <H2><A NAME="SEC137" HREF="unix_toc.html#TOC137">Generate WWW pages automagically</A></H2><P>The following program scans through the password database andbuild a standardized html-page for each user it finds there. Itfills in the name of the user in each case. Note the use ofthe <SAMP>`&#60;&#60;'</SAMP> operator for extended input, already used in thecontext of the shell, See section <A HREF="unix.html#SEC96">Pipes and redirection in csh</A>. This allowsus to format a whole passage of text, inserting variables atstrategic places, and avoid having to the <CODE>print</CODE> overmany lines.</P><PRE>#!/local/bin/perl## Build a default home page for each user in /etc/passwd####################################################################### Level 0 (main)####################################################################$true = 1;$false = 0;# First build an associated array of users and full namessetpwent();while ($true)   {   ($name,$passwd,$uid,$gid,$quota,$comment,$fullname) = getpwent;   $FullName{$name} = $fullname;   print "$name - $FullName{$name}\n";   last if ($name eq "");   }print "\n";# Now make a unique filename for each page and open a fileforeach $user (sort keys(%FullName))   {   next if ($user eq "");   print "Making page for $user\n";   $outputfile = "$user.html";   open (OUT,"&#62; $outputfile") || die "Can't open $outputfile\n";   &#38;MakePage;   close (OUT);   }##################################################################### Level 1####################################################################sub MakePage{print OUT &#60;&#60;ENDMARKER;&#60;HTML&#62;&#60;BODY&#62;&#60;HEAD&#62;&#60;TITLE&#62;$FullName{$user}'s Home Page&#60;/TITLE&#62;&#60;/HEAD&#62;&#60;H1&#62;$FullName{$user}'s Home Page&#60;/H1&#62;Hi welcome to my home page. In case you hadn'tgot it yet my name is: $FullName{$user}...I study at &#60;a href=http://www.iu.hio.no&#62;H&#38;oslash;gskolen i Oslo&#60;/a&#62;.&#60;/BODY&#62;&#60;/HTML&#62; ENDMARKER} </PRE><P> <H2><A NAME="SEC138" HREF="unix_toc.html#TOC138">Other supported functions</A></H2><P>Perl has very many functions which come directly from the C library.To give a taster, a few are listed here. The Perl book containsa comprehensive description of these.</P><DL COMPACT><DT><EM>Fork</EM><DD>The standard UNIX fork command for spawning new processes.<DT><EM>Sockets</EM><DD>Support for network socket communication.<DT><EM>Directories</EM><DD>Directory opening and handling routines.<DT><EM>Databases</EM><DD>Reading from the password files and the host databases is supported throughthe standard C functions <SAMP>`getpasswdbyname'</SAMP> etc. dressed up to look like Perl.<DT><EM>Crypt</EM><DD>The password encryption function.<DT><EM>Regexp</EM><DD>Regular expressions and pattern matching, search and replace functionsas in <SAMP>`sed'</SAMP>.<DT><EM>Operators</EM><DD>Perl has the full set of C's logical operators.<DT><EM>File testing</EM><DD>Tests from the shell like <SAMP>`if (-f file)'</SAMP>.</DL><P>Here are some of the most frequently used functions</P><DL COMPACT><DT><CODE>chmod</CODE><DD>Change the file mode of a file. e.g. <CODE>chmod 755,<VAR>filename</VAR></CODE><DT><CODE>chdir</CODE><DD>Change the current working directory. e.g. <CODE>chdir /etc</CODE><DT><CODE>stat</CODE><DD>Get info about permissions, ownership and type of a file.<DT><CODE>open</CODE><DD>Open a  file for reading, <SAMP>`&#62;'</SAMP> writing, <SAMP>`|'</SAMP> as a pipe.<DT><CODE>close</CODE><DD>Close an open file handle.<DT><CODE>system</CODE><DD>Execute a shell command as a child process. e.g. <CODE>system "ls";</CODE><DT><CODE>split</CODE><DD>Split a string variable into an array of elements, by searching for aspecial character (space or <SAMP>`:'</SAMP> etc.)e.g. <CODE>@array=split(":",$string)</CODE>.<DT><CODE>rename</CODE><DD>Rename a file. e.g. <CODE>rename <VAR>old name</VAR> <VAR>new-name</VAR></CODE><DT><CODE>mkdir</CODE><DD>Make a new directory. <CODE>mkdir <VAR>newdir</VAR></CODE><DT><CODE>shift</CODE><DD>Read the first element of an array and delete it, shifting all thearray elements down by one. (e.g. <CODE>$first=shift(@array);)</CODE>.<DT><CODE>chop</CODE><DD>Chops off the last character of a string. Often used for deleting theend-of-line character when reading from a file.<DT><CODE>oct</CODE><DD>Interprets a number as octal (converts to decimal). e.g.<CODE>$decimal = oct(755);</CODE><DT><CODE>kill</CODE><DD>Send a kill signal to a list of processes. e.g. <CODE>kill -9, <VAR>pid1</VAR>,<VAR>pid2</VAR>...</CODE></DL><P>You should explore Perl's possibilities yourself. Perl is a good alternativeto the shell which has much of the power of C and is thereforeideal for simple and more complex system programming tasks.If you intend to be a system administrator for UNIX systems, you coulddo much worse than to read the Perl book and learn Perl inside out.</P><P> <H2><A NAME="SEC139" HREF="unix_toc.html#TOC139">Summary</A></H2><P>The Practical Extraction and Report Language is a powerful tool whichgoes beyond shell programming, but which retains much of theimmediateness of shell programming in a more formal programmingenvironment.</P><P>The success of Perl has led many programmers to use it exclusively.  Inthe next section, I would like to argue that programming directly in Cis not much harder. In fact it has advantages in the long run. The powerof Perl is that it is as <EM>immediate</EM> as shell programming. If youare inexperienced, Perl is a little easier than C because many featuresare ready programmed into the language, but with time one also builds upa repertoire of C functions which can do the same tricks.</P><P> <H2><A NAME="SEC140" HREF="unix_toc.html#TOC140">Exercises</A></H2><OL><LI>Write a program which prints out all of its arguments alphabeticallytogether with the first and the last, and the number of arguments.<LI>Write a program which prints out the pathname of the home directoryfor a given user. The user's login name should be given as an argument.<LI>Write a program called `search-replace' which looks for a givenstring in a list of files and replaces it with a new string. You shouldbe able to specify a list of files using ordinary UNIX wildcards. e.g.<SAMP>`search-replace search-string replace-string *.text'</SAMP>. This is adangerous operation! What if the user types the strings incorrectly?How can you may the program safer?<LI>Write a program which opens a pipe from <SAMP>`ps'</SAMP> and computes thetotal cpu-time used by each user. Print the results in order of maximumto minimum. Hint: use an associated array to store the information.<LI>Write a program which forks and goes into the background. Make theprogram send you mail when some other user of your choice logs in. Use sleep to check only every few minutes.<LI>Open a pipe from <SAMP>`find'</SAMP> and collect statistics over how manyfiles there are in all of your sub-directories.</OL><P> <H2><A NAME="SEC141" HREF="unix_toc.html#TOC141">Project</A></H2><P>Write a program which checks the `sanity' of your UNIX system. <OL><LI>Check that the password file /etc/passwd is not writableby general users.<LI>Check that the processes <SAMP>`cron'</SAMP> and <SAMP>`sendmail'</SAMP> are running.<LI>Check that, if the file <SAMP>`/etc/exports'</SAMP>or <TT>`/etc/dfs/dfstab'</TT> exists, the <EM>nfsd</EM> daemonis running.<LI>Check that if the filesystem table <SAMP>`/etc/fstab'</SAMP> (or itsequivalent on non-BSD systems) contains NFS mounted filesystems, the<SAMP>`biod'</SAMP> or <SAMP>`nfsiod'</SAMP> daemon is running.<LI>Check that the file <SAMP>`/etc/resolv.conf'</SAMP> contains the correctdomain name. Itmay or may not be the same as that returned by the shell command <SAMP>`domainname'</SAMP>. If it is not the same, you shouldprint the message `NIS domain has different name to DNS domain'.</OL><H1><A NAME="SEC142" HREF="unix_toc.html#TOC142">WWW and CGI programming</A></H1><P>CGI stands for the Common Gateway Interface. It is the namegiven to scripts which can be executed from within pages of theworld wide web. Although it is possible to use any language inCGI programs (hence the word `common'), the usual choice isPerl, because of the ease with which Perl can handle text.</P><P>The CGI interface is pretty unintelligent, in order tobe as general as possible, so we need to do a bit of work inorder to make scripts work.</P><P> </P><H2><A NAME="SEC143" HREF="unix_toc.html#TOC143">Permissions</A></H2><P>The key thing about the WWW which often causes a lot of confusionis that the W3 service runs with a user ID of `nobody'. The purposeof this is to ensure that nobody has the right to read or write filesunless they are opened very explicitly by the user who owns them. </P><P>In order for files to be readable on the WWW, they must have file mode<SAMP>`644'</SAMP> and they must lie in a directory which has mode<SAMP>`755'</SAMP>. In order for a CGI program to be executable, it must havepermission <SAMP>`755'</SAMP> and in order for such a program to write toa file in a user's directory, it must be possible for the fileto be created (if necessary) and everyone must be able to writeto it. That means that files which are written to by the WWW must havemode <SAMP>`666'</SAMP> and must either exist already or lie in a directorywith permission <SAMP>`777'</SAMP><A NAME="DOCF6" HREF="unix_foot.html#FOOT6">(6)</A>.</P><P> <H2><A NAME="SEC144" HREF="unix_toc.html#TOC144">Protocols</A></H2><P>CGI script programs communicate with W3 browsers using a very simpleprotocol. It goes like this:</P><UL><LI>A web page sends data to a script using the `forms' interface.  Thosedata are concatenated into <EM>a single line</EM>. The data in separatefields of a form are separated by <SAMP>`&#38;'</SAMP> signs. New lines are replacedby the text <SAMP>`%0D%0A'</SAMP>, which is the DOS ASCII representation of anewline, and spaces are replaced by <SAMP>`+'</SAMP> symbols.<LI>A CGI script reads this single line of text on the standard input.<LI>The CGI script replies to the web browser. The first lineof the reply <EM>must</EM> be a line which is tells the browserwhat mime-type the data are sent in. Usually, a CGI scriptreplies in HTML code, in which case the first line in thereply must be:<PRE>  Content-type: text/html</PRE><A NAME="IDX779"></A><A NAME="IDX780"></A>This must be followed by a blank line.</UL><P> <H2><A NAME="SEC145" HREF="unix_toc.html#TOC145">HTML coding of forms</A></H2><P>To start a CGI program from a web page we use a <EM>form</EM><A NAME="IDX781"></A> which is a part of the HTML code enclosed with the parentheses</P><PRE> &#60;FORM method="POST" ACTION="/cgi-script-alias/program.pl"&#62;     ... &#60;/FORM&#62;</PRE><P>The method `post' means that the data which get typed intothis form will be piped into the CGI program via its standardinput. The `action' specifies which program you want to start.Note that<A NAME="IDX782"></A>you cannot simply use the absolute path of the file, for securityreasons. You must use something called a `script alias' to tell the webbrowser where to find the program. If you do not have a script aliasdefined for you personally, then you need to get one from your systemadministrator.  By using a script alias, no one from outside your sitecan see where your files are located, only that you have a `cgi-bin'area somewhere on your system.</P><P>Within these parentheses, you can arrange to collect different kinds ofinput. The simplest kind of input is just a button which startsthe CGI program. This has the form<PRE> &#60;INPUT TYPE="submit" VALUE="Start my program"&#62;</PRE><P>This code creates a button. When you click on it the programin your `action' string gets started. More generally, you willwant to create input boxes where you can type in data. To createa single line input field, you use the following syntax:<PRE> &#60;INPUT NAME="variable-name" SIZE=40&#62;</PRE><P>This creates a single line text field of width 40 characters.  This isnot the limit on the length of the string which can be typed into thefield, only a limit on the amount which is visible at any time. It isfor visual formatting only.  The NAME field is used to identify the datain the CGI script.  The string you enter here will be sent to the CGIscript in the form <SAMP>`variable-name=value of input...'</SAMP>.  Another typeof input is a text area. This is a larger box where one can type in texton several lines. The syntax is:<PRE> &#60;TEXTAREA NAME="variable-name" ROW=50 COLS=50&#62;</PRE><P>which means: create a text area of fifty rows by fifty columnswith a prompt to the left of the box. Again, the size has onlyto do with the visual formatting, not to do with limitson the amount of text which can be entered.</P><P>As an example, let's create a WWW page with a completeform which can be used to make a guest book, or orderform.</P><PRE>&#60;HTML&#62;&#60;HEAD&#62;&#60;TITLE&#62;Example form&#60;/TITLE&#62;&#60;!-- Comment: Mark Burgess, 27-Jan-1997 --&#62;&#60;LINK REV="made" HREF="mailto:mark@iu.hio.no"&#62;&#60;/HEAD&#62;&#60;BODY&#62;&#60;CENTER&#62;&#60;H1&#62;Write in my guest book...&#60;/H1&#62;&#60;/CENTER&#62;&#60;HR&#62;&#60;CENTER&#62;&#60;H2&#62;Please leave a comment using the form below.&#60;/H2&#62;&#60;P&#62;&#60;FORM method="POST" ACTION="/cgi-bin-mark/comment.pl"&#62;Your Name/e-mail: &#60;INPUT NAME="variable1" SIZE=40&#62; &#60;BR&#62;&#60;BR&#62;&#60;P&#62;&#60;TEXTAREA NAME="variable2" cols=50 rows=8&#62;&#60;/TEXTAREA&#62;&#60;P&#62;&#60;INPUT TYPE=submit VALUE="Add message to book"&#62;&#60;INPUT TYPE=reset VALUE="Clear message"&#62;&#60;/FORM&#62;&#60;P&#62;&#60;/BODY&#62;&#60;/HTML&#62;</PRE><P></P><P>The reset button clears the form. When the submit button is pressed,the CGI program is activated.</P><P> <H2><A NAME="SEC146" HREF="unix_toc.html#TOC146">Perl and the web</A></H2><P> </P><H3><A NAME="SEC147" HREF="unix_toc.html#TOC147">Interpreting data from forms</A></H3><P>To interpret and respond to the data in a form, we must write a programwhich satisfies the protocol above, See section <A HREF="unix.html#SEC144">Protocols</A>.  We useperl as a script language.  The simplest valid CGI script is thefollowing:</P><PRE>#!/local/bin/perl # # Reply with proper protocol #print "Content-type: text/html\n\n"; # # Get the data from the form ... #$input = &#60;STDIN&#62;; # # ... and echo them back #print $input, "\n Done! \n";</PRE><P>Although rather banal, this script is a useful starting point for CGIprogramming, because it shows you just how the input arrives at thescript from the HTML form. The data arrive all in a single, enormouslylong line, full of funny characters. The first job of any script is todecode this line.</P><P>Before looking at how to decode the data, we should make an importantpoint about the protocol line. If a web browser does not get this`Content-type' line from the CGI script it returns with an error:</P><PRE>500 Server ErrorThe server encountered an internal error or misconfiguration and wasunable to complete your request.Please contact the server administrator, and inform them of the time the error occurred, and anything you might have done that may have caused the error.Error: HTTPd: malformed header from script www/cgi-bin/comment.pl </PRE><P>Before finishing your CGI script, you will probably encounter this errorseveral times. A common reason for getting the error is a syntax errorin your script. If your program contains an error, the first thing abrowser gets in return is not the `Content-type' line, but an errormessage.  The browser does not pass on this error message, it justprints the uninformative message above.</P><P>If you can get the above script to work, then you are ready todecode the data which are sent to the script. The first thingis to use perl to split the long line into an array of lines, bysplitting on <SAMP>`&#38;'</SAMP>. We can also convert all of the <SAMP>`+'</SAMP>symbols back into spaces. The script now looks like this:</P><PRE>#!/local/bin/perl # # Reply with proper protocol #print "Content-type: text/html\n\n"; # # Get the data from the form ... #$input = &#60;STDIN&#62;; # # ... and echo them back #print "$input\n\n\n";$input =~ s/\+/ /g; # # Now split the lines and convert #@array = split('&#38;',$input);foreach $var ( @array )   {   print "$var\n";   }print "Done! \n";</PRE><P>We now have a series of elements in our array. The output from thisscript is something like this:</P><PRE>variable1=Mark+Burgess&#38;variable2=%0D%0AI+just+called+to+say+ <VAR>(wrap)</VAR>....%0D%0A...hey+pig%2C+nothing%27s+working+out+the+way+I+plannedvariable1=Mark Burgess variable2=%0D%0AI just called to say  <VAR>(wrap)</VAR>....%0D%0A...hey pig%2Cnothing%27s working out the way I planned Done! </PRE><P>As you can see, all control characters are converted into the form <SAMP>`%XX'</SAMP>.We should now try to do something with these. Since we are usually not interestedin keeping new lines, or any other control codes, we can simply null-out thesewith a line of the form</P><PRE>$input =~ s/%..//g;</PRE><P>The regular expression <SAMP>`%..'</SAMP> matches anything beginning with a percentsymbol followed by two characters. The resulting output is then free ofthese symbols. We can then separate the variable contents from their namesby splitting the input. Here is the complete code:</P><PRE>#!/local/bin/perl # # Reply with proper protocol #print "Content-type: text/html\n\n"; # # Get the data from the form ... #$input = &#60;STDIN&#62;; # # ... and echo them back #print "$input\n\n\n";$input =~ s/%..//g;$input =~ s/\+/ /g;@array = split('&#38;',$input);foreach $var ( @array )   {   print "$var&#60;br&#62;";   }print "&#60;hr&#62;\n";($name,$variable1) = split("variable1=",$array[0]);($name,$variable2) = split("variable2=",$array[1]);print "&#60;br&#62;var1 = $variable1&#60;br&#62;";print "&#60;br&#62;var2 = $variable2&#60;br&#62;";print "&#60;br&#62;Done! \n";</PRE><P>and the output</P><PRE>variable1=Mark+Burgess&#38;variable2=%0D%0AI+just+called+to+say <VAR>(wrap)</VAR>+....%0D%0A...hey+pig%2C+nothing%27s+working+out+the+way+I+plannedvariable1=Mark Burgessvariable2=I just called to say .......hey pig nothings working <VAR>(wrap)</VAR> out the way I planned var1 = Mark Burgessvar2 = I just called to say .......hey pig nothings working out  <VAR>(wrap)</VAR>the way I planned Done! </PRE><P> <H3><A NAME="SEC148" HREF="unix_toc.html#TOC148">A complete guestbook example in perl</A></H3><P>Let us now use this technique to develop a guest book application.Based on the code above, analyze the following code.</P><PRE>#!/local/bin/perl###################################################################### Guest book#####################################################################$guestbook_page = "/iu/nexus/ud/mark/www/tmp/cfguest.html";$tmp_page = "/iu/nexus/ud/mark/www/tmp/guests.tmp";  $remote_host = $ENV{"REMOTE_HOST"};print "Content-type: text/html\n\n";print "&#60;br&#62;&#60;hr&#62;&#60;br&#62;\n";print "Thank you for submitting your comment!&#60;br&#62;&#60;br&#62;\n";print "best wishes,&#60;br&#62;&#60;br&#62;";print "-Mark&#60;br&#62;&#60;br&#62;&#60;br&#62;";print "Return to &#60;a href=http://www.iu.hio.no/~mark/menu.html&#62;menu&#60;/a&#62;\n";$input = &#60;STDIN&#62;;$input =~ s/%..//g;$input =~ s/\+/ /g;@array = split('&#38;',$input);($skip,$name) = split("var1=",$array[0]);($skip,$message) = split("var2=",$array[1]);if (! open (PAGE, $guestbook_page))    {   print "Content-type: text/html\n\n";   print "couldn't open guestbook page file!";   }if (! open (TMP, "+&#62;$tmp_page"))   {   print "Content-type: text/html\n\n";   print "couldn't open temporary output file!";    }while ($line = &#60;PAGE&#62;)   {   if ($line =~ /&#60;h3&#62;Number of entries: (..)/)      {      $entry_no = $1;      $entry_no++;      $line = "&#60;h3&#62;Number of entries: $entry_no &#60;/h3&#62;\n";      }    if ($line =~ /&#60;!-- LAST ENTRY --&#62;/)       {       $date = `date +"%A, %b %d %Y"`;	       print TMP "&#60;b&#62;Entry $date from host: $remote_host&#60;/b&#62;\n&#60;p&#62;\n";       print TMP "From: $name\n&#60;p&#62;\n";       print TMP $message;       print TMP "\n&#60;hr&#62;\n";       }    print TMP "$line";    }    close PAGE;close TMP;if (! rename ($tmp_page, $guestbook_page))   {   print "Oops! Rename operation failed!\n";   }chmod (0600, $guestbook_page);</PRE><P>This script works by reading through the old guest book file, opening anew copy of the guest book file and appending a new messages at theend. The end of the message section (not counting the <SAMP>`&#60;/HTML&#62;'</SAMP>tags) is marked by a comment line. </P><PRE>&#60;!-- LAST ENTRY --&#62;</PRE><P>Note that a provisional guest book file has to exist in the first place.The script writes to a new file and then swaps the new file for the oldone. The guest book file looks something like this:<PRE>&#60;html&#62;&#60;head&#62;&#60;title&#62;Comments&#60;/title&#62;&#60;/head&#62;&#60;body&#62;&#60;h1&#62;My guest book&#60;/h1&#62; &#60;b&#62;Entry no.  Wednesday, Feb 28 1996 from host: dax&#60;/b&#62;&#60;p&#62;From: Mark.Burgess@iu.hio.no&#60;p&#62;Just to start the ball rolling.... &#60;hr&#62;&#60;b&#62;Entry no.  Tuesday, Mar 26 1996 from host: enterprise.subspace.net&#60;/b&#62;&#60;p&#62;From: spock@enterprise&#60;p&#62;Registering a form of energy never before encountered. &#60;!-- LAST ENTRY --&#62; &#60;/body&#62; &#60;address&#62;&#60;a href="http://www.iu.hio.no/~mark"&#62;MarkBurgess&#60;/a&#62; - Mark.Burgess@iu.hio.no&#60;/addre ss&#62; &#60;/html&#62;</PRE><P>The directory in which this file lies needs to be writable tothe user nobody (the WWW user) and the files within need to bedeletable by nobody but no one else. Some users try to makeguest book scripts setuid-themselves in order to overcome theproblem that httpd runs with uid nobody, but this opens manysecurity issues. In short it is asking for trouble. Unfortunatelyan ordinary user cannot use <CODE>chown</CODE> in order to give accessonly to the WWW user nobody, so this approach needs the cooperationof the system administrator. Nevertheless this is the most secureapproach.Try to work through this example step for step.</P><P> <H2><A NAME="SEC149" HREF="unix_toc.html#TOC149">PHP and the web</A></H2><P>The PHP language makes the whole business of web programming rathersimpler than perl. It hides the business of translating variablesfrom forms into new variables in a CGI program and it even allows youto embed active code into you HTML pages. PHP has special support forquerying data in an SQL database like MySQL or Oracle. PHP documentationlives at @uref{http://www.php.net}.</P><H3><A NAME="SEC150" HREF="unix_toc.html#TOC150">Embedded PHP</A></H3><P>PHP code can be embedded inside HTML pages provided your WWW server isconfigurered with PHP support. PHP code lives inside a tag with thegeneral form<PRE>  &#60;?php <VAR>code...</VAR>  ?&#62;</PRE><P>For example, we could use this to import one file into anotherand print out a table of numbers:<PRE>&#60;html&#62;&#60;body&#62;&#60;?php include "file.html" for ($i = 0; $i &#60; 10; $i++)   {   print "Counting $i&#60;br&#62;";   }?&#62;&#60;/body&#62;&#60;/html&#62;</PRE><P>This makes it easy to generate WWW pages with a fixed visual layout:</P><PRE>&#60;?php## Standard layout## Set $title, $comment and $contents##########################################################################print "&#60;body&#62;\n";print "&#60;img src=img/header.gif&#62;";print "&#60;h1&#62;"$title&#60;/h1&#62;";print "&#60;em&#62;$comment&#60;/em&#62;";print "&#60;blockquote&#62;\n";include $contents;print ("&#60;/blockquote&#62;\n");print ("&#60;/body&#62;\n");print ("&#60;/html&#62;\n");</PRE><P>Variables are easily set by calling PHP code in the form of a CGI programfrom a form.</P><H3><A NAME="SEC151" HREF="unix_toc.html#TOC151">PHP and forms</A></H3><P>PHP is particularly good at dealing with forms, as a CGI scriptinglanguage. Consider the following form:</P><PRE>&#60;html&#62;&#60;body&#62;&#60;form action="/cgi-bin-scriptalias/spititout.php" method="post"&#62;    Name:  &#60;input type="text" name="personal[name]"&#62;&#60;br&#62;    Email: &#60;input type="text" name="personal[email]"&#62;&#60;br&#62;    Preferred language:    &#60;select multiple name="language[]"&#62;        &#60;option value="English"&#62;English        &#60;option value="Norwegian"&#62;Norwegian        &#60;option value="Gobbledigook"&#62;Gobbledigook    &#60;/select&#62;        &#60;input type=image src="image.gif" name="sub"&#62;&#60;/form&#62;&#60;/body&#62;&#60;/html&#62;</PRE><P>This produces a page into which one types a name and email addressand chooses a language from a list of three possible choices. When theuser clicks on a button marked by the file <TT>`image.gif'</TT> theform is posted. Here is a program which unravels the data sent to theCGI program:</P><PRE>#!/local/bin/php&#60;?php## A CGI program which handles a form# Variables are translated automatically#$title = "This page title";$comment = "This pages talks about the following.....";##########################################################################echo "&#60;body&#62;";echo "&#60;h1&#62;$title&#60;/h1&#62;";echo "&#60;em&#62;$comment&#60;/em&#62;";echo "&#60;blockquote&#62;\n";### echo "Your name is $personal[name]&#60;br&#62;&#60;br&#62;"; echo "Your email is $personal[email]&#60;br&#62;&#60;br&#62;"; echo "Language options: "; echo "&#60;table&#62; "; for ($i = 0; strlen($language[$i]) &#62; 0; $i++)    {    echo "&#60;tr&#62;&#60;td bgcolor=#ff0000&#62;Variable language[$i] = $language[$i]&#60;/td&#62;&#60;/tr&#62;";    } if ($language[0] == "Norwegian")    {    echo "Hei alle sammen&#60;p&#62;";    } else    {    echo "Greetings everyone, this page will be in English&#60;p&#62;";    } echo "&#60;/table&#62; ";###echo ("&#60;/blockquote&#62;\n");echo ("&#60;/body&#62;\n");echo ("&#60;/html&#62;\n");?&#62;</PRE><H3><A NAME="SEC152" HREF="unix_toc.html#TOC152">A complete PHP guestbook</A></H3><P>If your web-server supports PHP there is no need for separate CGI-scripts handling form output. A single PHP-script can create the form and handle the output simultaneously. In addition this script can be placed wherever the web-server is able to read HTML files. PHP defines a special variable <CODE>$PHP_SELF</CODE> which provides the <CODE>action=</CODE> assignment of the form with the script itself. Moreover such PHP-scripts checks whether the user has submitted any data by checking if the variables of the form is set with the command <CODE>isset()</CODE>. The following code shows how easily a guestbook can be made using PHP compared to the Perl-code shown in a previous section. See section <A HREF="unix.html#SEC148">A complete guestbook example in perl</A>.</P><PRE>&#60;html&#62;&#60;head&#62;&#60;title&#62;My Guestbook&#60;/title&#62;&#60;/head&#62;&#60;body&#62;&#60;h1&#62;Welcome to my Guestbook&#60;/h1&#62;&#60;h2&#62;Please write me a little note below&#60;/h2&#62;&#60;form action="&#60;?echo $PHP_SELF?&#62;" method="POST"&#62;&#60;textarea cols=40 rows=5 name=note wrap=virtual&#62;&#60;/textarea&#62;&#60;input type=submit value=" Send it "&#62;&#60;/form&#62;&#60;?php  $file = "/iu/nexus/ud/haugerud/www/cgi-out/guestbook.txt";  if(isset($note))     {    $date = date("F j, Y, G:i");    $buffer = "&#60;h3&#62;Message sent from IP-address $REMOTE_ADDR&#60;/h3&#62;\n";    $buffer .= "&#60;h4&#62;$date&#60;/h4&#62;\n";    $buffer .= nl2br($note).'&#60;br&#62;';    $handle = fopen ($file, "r");     while (!feof($handle))         {     	$buffer .= fread($handle,4096);     	}     fclose($handle);     $outhandle=fopen ($file,"w");     fputs($outhandle,$buffer);     fclose($outhandle);   }?&#62;&#60;h2&#62;The entries so far:&#60;/h2&#62;&#60;? @ReadFile($file) ?&#62;&#60;/body&#62;&#60;/html&#62; </PRE><H1><A NAME="SEC153" HREF="unix_toc.html#TOC153">C programming</A></H1><P><EM>This section is not meant to teach you C. It is a guide to using Cin UNIX and it is assumed that you have a working knowledge of thelanguage. See the GNU C-Tutorial for an introduction to basics.</EM></P><P> </P><H2><A NAME="SEC154" HREF="unix_toc.html#TOC154">Shell or C?</A></H2><P><A NAME="IDX783"></A>In the preceding chapters we have been looking at ways to get simpleprogramming tasks done. The immediateness of the script languages is agreat advantage when we just want to get a job done as quickly aspossible.  Scripts lend themselves to simple system administration taskslike file processing, but they do not easily lend themselves to moreserious programs.</P><P><A NAME="IDX784"></A>Although some system administrators have grown to the idea that shellprogramming is easier, I would argue that this is not really true.First of all, most of the UNIX shell commands are just wrapper programsfor C function calls. Why use the wrapper when you can use the realthing? Secondly, the C function calls return data in pointers andstructures which are very easy to manipulate, whereas piping the outputof shell programs into others can be a very messy and awkward way ofworking.  Here are some of the reasons why we also need a moretraditional programming language like C.</P><OL><LI>The shell languages do not allow us to create an acceptableuser-interface, like X-windows, or the curses (cursor manipulation)library. They are mainly intended for file-processing. (Thoughrecently the <EM>Tk</EM> library has provided a way of creatinguser interfaces in Tcl and Perl.)<A NAME="IDX785"></A><A NAME="IDX786"></A><A NAME="IDX787"></A><LI>Shell commands read their input line-by-line. Not all inputis generated in this simple way -- we also need to be able to readthrough lines i.e. the concept of a  <EM>data stream</EM>. <LI>More advanced data structures are needed for most applications, suchas linked lists and binary trees, acyclic graphs etc. <LI>Compilers help to sort out simple typographical and logical errorsby compile-time checking source code. <LI>Compiled code is faster than interpreted code.<LI>Many tools have been written to help in the programming of C code(dbx, lex, yacc etc.).<A NAME="IDX788"></A><A NAME="IDX789"></A></OL><P> <H2><A NAME="SEC155" HREF="unix_toc.html#TOC155">C program structure</A></H2><P> </P><H3><A NAME="SEC156" HREF="unix_toc.html#TOC156">The form of a C program</A></H3><P>A C program consists of a set of function, beginningwith the main program:</P><PRE>main ()   /* This is a comment */{Commands ...}</PRE><P>The source code of a C program can be divided into several text files.C compiles all functions separately; the linker <CODE>ld</CODE> joins them allup at the end. This means that we can plan out a strategy for writinglarge programs in a clear and efficient manner. </P><P>NOTE: C++ style comments <SAMP>`//...'</SAMP> are not allowed by mostC compilers.</P><P> <H3><A NAME="SEC157" HREF="unix_toc.html#TOC157">Macros and declarations</A></H3><P>Most UNIX systems now have ANSI C compatible compilers, but this has notalways been the case. Most UNIX programs written in a versionof C which is older than the ANSI standard, so you will need anappreciation of old Kernighan and Ritchie C conventions for Cprogramming. See for example my C book.</P><P>An obvious difference between ANSI C and K&#38;R C is that the C++additions to the language are not included. Here are some usefulpoints to remember.<A NAME="IDX790"></A><A NAME="IDX791"></A></P><UL><LI>K&#38;R C does not allow <SAMP>`const'</SAMP> data, it uses the C preprocessor with<SAMP>`#define'</SAMP> instead. i.e. instead of<PRE>const int blah = 1;</PRE>use<PRE>#define blah 1</PRE>Remember that the hash symbol <SAMP>`#'</SAMP> must be the first character ona line under UNIX.<LI>K&#38;R C doesn't use function prototypes or declarations of the form:<PRE>void function (char *string, int a, int b){}</PRE>Instead one writes:<PRE>void function (string, a, b)char *string;int a,b;{}</PRE></UL><P> <H3><A NAME="SEC158" HREF="unix_toc.html#TOC158">Several files</A></H3><P>Most UNIX programs are very large and are split up into many files.Remember, when you split up programs into several files, you mustdeclare variables as <SAMP>`extern'</SAMP> in file A if they are really declaredin file B.  in which you want to use them. This tells the compiler thatit should not try to create local storage for the variable, because this wasalready done in another file.</P><P><A NAME="IDX792"></A><A NAME="IDX793"></A></P><P> <H2><A NAME="SEC159" HREF="unix_toc.html#TOC159">A note about UNIX system calls and standards</A></H2><P><A NAME="IDX794"></A>Most of the system calls in UNIX return data in the form of <SAMP>`struct'</SAMP>variables. Sometimes these are structures used by the operating systemitself -- in other cases they are just put together so that programmerscan handle a packet of data in a convenient way.</P><P>If in doubt, you can find the definitions of these structures in therelevant include files under <TT>`/usr/include'</TT>.</P><P>Since UNIX comes in many flavours the system calls are not alwayscompatible and may have different options and arguments. Becauseof this there is a number of standardizing organizations for UNIX.One of them is POSIX which is an organization run by themajor UNIX vendors. Programs written for UNIX are nowexpected to be POSIX compliant. This is not something you need tothink about at the level of this course, but you should certainlyremember that there exist programming standards and that these shouldbe adhered to. The aim is to work towards a single standard UNIX.</P><P> <H2><A NAME="SEC160" HREF="unix_toc.html#TOC160">Compiling: <SAMP>`cc'</SAMP>, <SAMP>`ld'</SAMP> and <TT>`a.out'</TT></A></H2><P>The C compiler on the UNIX system is traditionally called <SAMP>`cc'</SAMP> andhas always been a traditional part of every UNIX environment. Recentlyseveral UNIX vendors have stopped including the C compiler as a part oftheir operating systems and instead sell a compiler separately.Fortunately there is a public domain Free Software version of thecompiler called <SAMP>`gcc'</SAMP> (the GNU C compiler). We shall use this inall the examples.</P><P>To compile a program consisting of several files of code,we first compile all of the separate pieces without trying to linkthem. There are therefore two stages: first we turn <SAMP>`.c'</SAMP>files into <SAMP>`.o'</SAMP> files. This compiles code but does notfix any address references. Then we link all <SAMP>`.o'</SAMP>files into the final executable, including any librarieswhich are used.</P><P><A NAME="IDX795"></A><A NAME="IDX796"></A>Let's suppose we have files <TT>`a.c'</TT>, <TT>`b.c'</TT> and <TT>`c.c'</TT>.We write:<PRE>  gcc -c a.c b.c c.c</PRE><P>This creates files <SAMP>`a.o'</SAMP>, <SAMP>`b.o'</SAMP> and <SAMP>`c.o'</SAMP>.Next we link them into one file called `myprog'.<PRE>  gcc -o myprog  a.o b.o c.o</PRE><P>If the naming option <SAMP>`-o myprog'</SAMP> is not used, the link <SAMP>`ld'</SAMP>uses the default name <EM>a.out</EM> for the executable file.<A NAME="IDX797"></A></P><P> </P><H3><A NAME="SEC161" HREF="unix_toc.html#TOC161">Libraries and <SAMP>`LD_LIBRARY_PATH'</SAMP></A></H3><P><A NAME="IDX798"></A><A NAME="IDX799"></A><A NAME="IDX800"></A><A NAME="IDX801"></A><A NAME="IDX802"></A><A NAME="IDX803"></A>The resulting file is called <SAMP>`myprog'</SAMP> and includes references onlyto the standard library <SAMP>`libc'</SAMP>. If we wish to link in the mathlibrary <SAMP>`libm'</SAMP> or the cursor movement library <SAMP>`libcurses'</SAMP> --or in general, a library called <SAMP>`libBLAH'</SAMP> , we need to use the<SAMP>`-l'</SAMP> directive.</P><PRE>gcc -o myprog files.o  -lm -lcurses -lBLAH</PRE><P>The compiler looks for a suitable library in all of the directorieslisted in the environment variable <SAMP>`LD_LIBRARY_PATH'</SAMP>. Alternativelywe can add a directory to the search path by using the <SAMP>`-L'</SAMP>.option:<PRE>gcc -o myprog files.o -L/usr/local/lib -lm -lcurses -lBLAH </PRE><P> <H3><A NAME="SEC162" HREF="unix_toc.html#TOC162">Include files</A></H3><P><A NAME="IDX804"></A>Normally the compiler looks for include files only in thedirectory <TT>`/usr/include'</TT>. We can add further paths to searchusing the <SAMP>`-I'</SAMP> option.<PRE>gcc -o myprog file.c  -I/usr/local/include -I/usr/local/X11/include</PRE><P><A NAME="IDX805"></A><A NAME="IDX806"></A></P><P>Previously, UNIX libraries have been in <TT>`a.out'</TT> code format, butrecent releases of UNIX have gone over to a more efficient and flexibleformat called ELF (executable and linking format).</P><P> <H3><A NAME="SEC163" HREF="unix_toc.html#TOC163">Shared and static libraries</A></H3><P><A NAME="IDX807"></A><A NAME="IDX808"></A>Libraries are collections of C functions which the operating systemcreators have written for our convenience. The source code for such alibrary is just the source for a collection of functions -- there is no<CODE>main</CODE> program.</P><P>There are two kinds of library used by modern operating systems:<EM>archive libraries</EM> or static libraries and <CODE>shared libraries</CODE> or dynamical libraries. An archivelibrary has a name of the form<PRE> lib<VAR>name</VAR>.a</PRE><P>When an archive library is linked to a program, it is appendedlock, stock and barrel to the program code. This uses a lotof disk space and makes the size of the compiled program very large.Shared libraries (shared objects <SAMP>`so'</SAMP> or shared archives <SAMP>`sa'</SAMP>generally have names of the form)<PRE>  lib<VAR>name</VAR>.so  lib<VAR>name</VAR>.sa</PRE><P>often with version numbers appended. When a program islinked with a shared library the code is not appendedto the program. Instead pointers to the shared objectsare created and the library is loaded at runtime,thus avoiding the problem of having to store the libraryeffectively multiple times on the disk.</P><P>To make an archive library we compile all ofthe functions we wish to include in the library</P><PRE>gcc -c function1.c function2.c ...</PRE><P>and then join the files using the <SAMP>`ar'</SAMP> command.</P><PRE>ar rcv libMYLIB.a function1.oar rcv libMYLIB.a function2.o</PRE><P>To make a shared library one provides an option to the linkerprogram. The exact method is different in different operating systems,so you should look at the manual page for <CODE>ld</CODE> on your system.Under SunOS 4 we take the object files <SAMP>`*.o'</SAMP> and run<PRE> ld -o libMYLIB.so.1.1 -assert pure-text *.o</PRE><P>Under HPUX, we write<PRE> ld -b -o libMYLIB.so.1.1 *.o</PRE><P>With the GNU linker, you write<PRE> ld -shared -o libMYLIB.so.1.1 *.o</PRE><P>NOTE: when you add a shared library to the system under SunOS orGNU/Linux you must run the command <SAMP>`ldconfig'</SAMP>, making sure that thepath to the library is included in <SAMP>`LD_LIBRARY_PATH'</SAMP>. SunOS andGNU/Linux use a cache file <TT>`/etc/ld.so.cache'</TT> to keep currentversions of libraries. GNU/Linux also uses a configuration file called<TT>`/etc/ld.so.conf'</TT>.<A NAME="IDX809"></A><A NAME="IDX810"></A></P><P> <H3><A NAME="SEC164" HREF="unix_toc.html#TOC164">Knowing about important paths: directory structure</A></H3><P>It is important to understand how the C compiler finds the files it needs.We have already mentioned the <SAMP>`-I'</SAMP> and <SAMP>`-L'</SAMP> options to the compilation command line. In general, all system include files can befound in the directory <TT>`/usr/include'</TT> and subdirectories of thisdirectory.  All system libraries can be found in <TT>`/usr/lib'</TT>.</P><P>Many packages build their own libraries and keep the relevant filesin separate directories so that if the system gets reinstalled, theydo not get deleted. This is true for example of the X-windows system.The include and library files for this are typically kept indirectories which look something like <TT>`/usr/local/X11R5/include'</TT>and <TT>`/usr/X11R6/lib'</TT>. That means that we need to give all ofthis information to the compiler. Compiling a program becomesa complicated task in many cases so we need some kind of scriptto help us perform the task. The UNIX tool <CODE>make</CODE> was designedfor this purpose.</P><P> <H2><A NAME="SEC165" HREF="unix_toc.html#TOC165">Make</A></H2><P>Nowadays compilers are often sold with fancy user environments driven bymenus which make it easier to compile programs.  UNIX has similarenvironments but all of them use shell-based command line compilationbeneath the surface. That is because UNIX programmers are used towriting large and complex programs which occupy many directories andsubdirectories.  Each directory has to be adapted or configured to fit theparticular flavour of UNIX system it is being compiled upon. Interactiveuser environments are very poor at performing this kind of service. UNIXsolves the problem of compiling enormous <EM>trees</EM> of software (suchas the UNIX system itself!) by using a compilation language called<SAMP>`make'</SAMP>. Such language files can be generated automatically byscripts, allowing very complex programs to configure and compilethemselves from a single control script.<A NAME="IDX811"></A></P><P> </P><H3><A NAME="SEC166" HREF="unix_toc.html#TOC166">Compiling large projects</A></H3><P>Typing lines like<PRE>  cc -c file1.c file2.c ...  cc -o target file1.o ....</PRE><P></P><P>repeatedly to compile a complicated program can be a real nuisance. Onepossibility would therefore be to keep all the commands in a script.This could waste a lot of time though. Suppose you are working on a bigproject which consists of many lines of source code -- but are editingonly one file. You really only want to recompile the file you areworking on and then relink the resulting object file with all of theother object files. Recompiling the other files which hadn't changedwould be a waste of time.  But that would mean that you would have tochange the script each time you change what you need to compile.</P><P>A better solution is to use the <SAMP>`make'</SAMP> command. <SAMP>`make'</SAMP> wasdesigned for precisely this purpose. To use <SAMP>`make'</SAMP>, we createa file called <TT>`Makefile'</TT> in the same directory as our program.<SAMP>`make'</SAMP> is a quite general program for building software. It isnot specifically tied to the C programming language---it can be used in any programming language.</P><P>A <SAMP>`make'</SAMP> configuration file, called a <TT>`Makefile'</TT>, containsrules which describe how to compile or build all of the pieces ofa program.  For example, even without telling it specifically,<CODE>make</CODE> knows that in order to go from <SAMP>`prog.c'</SAMP> to<SAMP>`prog.o'</SAMP> the command <SAMP>`cc -c prog.c'</SAMP> must be executed.  AMakefile works by making such associations.  The Makefile contains alist of all of the files which compose the program and rules as to howto get to the finished product from the source.</P><P>The idea is that, to compile a program, we just have to type <KBD>make</KBD>.<SAMP>`make'</SAMP> then reads the Makefile and compiles all of the parts whichneed compiling. It does not recompile files which have not changed sincethe last compilation! How does it do this? <SAMP>`make'</SAMP> works bycomparing the time-stamp on the file it needs to create with thetime-stamp on the file which is to be compiled. If the compiled versionexists and is newer than its source then the source does not need to berecompiled.</P><P>To make this idea work in practice, <SAMP>`make'</SAMP> has to know how togo through the steps of compiling a program. Some default rules aredefined in a global configuration file, e.g.<PRE>/usr/include/make/default.mk</PRE><P>Let's consider an example of what happens for the the three files<TT>`a.c'</TT>, <TT>`b.c'</TT> and <TT>`c.c'</TT> in the example above -- andlet's not worry about what the Makefile looks like yet. </P><P>The first time we compile, only the `.c' files exist. When we type<SAMP>`make'</SAMP>, the program looks at its rules and finds that ithas to make a file called `myprog'. To make thisit needs to execute the command<PRE>  gcc -o myprog  a.o b.o c.o</PRE><P>So it looks for `a.o' etc and doesn't find them.  It now goes to a kindof subroutine and looks to see if it has any rules for making filescalled `.o' and it discovers that these are made by compiling with the<SAMP>`gcc -c'</SAMP> option. Since the files do not exist, it does this.  Nowthe files `a.o b.o c.o' exist and it jumps back to the original problemof trying to make `myprog'.  All the files it needs now exist and so itexecutes the command and builds `myprog'.</P><P>If we now edit `a.c', and type <SAMP>`make'</SAMP> once again -- it goesthrough the same procedure as before but now it finds all of thefiles. So it compares the dates on the files -- if the sourceis newer than the result, it recompiles. </P><P>By using this recursive method, <SAMP>`make'</SAMP> only compiles thoseparts of a program which need compiling.</P><P> <H3><A NAME="SEC167" HREF="unix_toc.html#TOC167">Makefiles</A></H3><P><A NAME="IDX812"></A><A NAME="IDX813"></A></P><P>To write a Makefile, we have to tell <SAMP>`make'</SAMP> about <EM>dependencies</EM>.The dependencies of a file are all of those files which are requiredto build it. Thus, the dependencies of `myprog' are `a.o', `b.o'and `c.o'. The dependencies of `a.o' are simply `a.c',the dependencies of `b.o' are `b.c' and so on.</P><P>A Makefile consists of rules of the form:</P><PRE>target : dependencies<KBD>TAB</KBD>                   rule;</PRE><P>The target is the thing we want to build, the dependencies arelike subroutines to be executed first if they do not exist. Finallythe rule is to be executed if all if the dependencies exist; it takesthe dependencies and turns them into the target.There are two important things to remember:</P><UL><LI>The file names must start on the first character ofa line.<LI>There must be a <KBD>TAB</KBD> character at the beginningof every rule or action. If there are spaces instead of tabs, or notab at all, <SAMP>`make'</SAMP> will signal an error. This bizarre featurecan cause a lot of confusion.</UL><P>Let's look at an example Makefile for a program which consists of twocourse files <TT>`main.c'</TT> and <TT>`other.c'</TT> and which makes use of alibrary called <TT>`libdb'</TT> which lies in the directory <TT>`/usr/local/lib'</TT>.Our aim is to build a program called <CODE>database</CODE>:</P><PRE>## Simple Makefile for `database'## First define a macroOBJ = main.o other.oCC = gccCFLAGS = -I/usr/local/includeLDFLAGS = -L/usr/local/lib -ldbINSTALLDIR = /usr/local/bin## Rules start here. Note that the $@ variable becomes the name of the# executable file. In this case it is taken from the ${OBJ} variable#database: ${OBJ}          ${CC} -o $@ ${OBJ} ${LDFLAGS}## If a header file changes, normally we need to recompile everything.# There is no way that make can know this unless we write a rule which# forces it to rebuild all .o files if the header file changes...#${OBJ}: ${HEADERS}## As well as special rules for special files we can also define a# "suffix rule". This is a rule which tells us how to build all files# of a certain type. Here is a rule to get .o files from .c files.# The $&#60; variable is like $? but is only used in suffix rules.#.c.o:           ${CC} -c ${CFLAGS} $&#60;######################################################################## Clean up####################################################################### # # Make can also perform ordinary shell command jobs # "make tidy" here performs a cleanup operation #clean:         rm -f ${OBJ}         rm -f y.tab.c lex.yy.c y.tab.h         rm -f y.tab lex.yy         rm -f *% *~ *.o         rm -f mconfig.tab.c mconfig.tab.h a.out         rm -f man.dvi man.aux man.log man.toc         rm -f cfengine.tar.gz cfengine.tar cfengine.tar.Z         make tidy         rm -f cfengineinstall: ${INSTALLDIR}/database        cp database ${INSTALLDIR}/database</PRE><P>The Makefile above can be invoked in several ways.<PRE>makemake databasemake cleanmake install</PRE><P>If we simple type <SAMP>`make'</SAMP> i.e. the first of these choices, <SAMP>`make'</SAMP>takes the first of the rules it finds as the object to build. In thiscase the rule is `database', so the first two forms above are equivalent.</P><P>On the other hand, if we type <PRE>make clean</PRE><P>then execution starts at the rule for `clean', which is normally usedto remove all files except the original source code. Make `install'causes the compiled program to be installed at its intended destination.</P><P><SAMP>`make'</SAMP> uses some special variables (which resemble the specialvariables used in Perl -- but don't confuse them). The most useful oneis <SAMP>`$@'</SAMP> which represents the current <EM>target</EM> -- or theobject which <SAMP>`make'</SAMP> would like to compile. i.e. as <SAMP>`make'</SAMP>checks each file it would like to compile, <SAMP>`$@'</SAMP> is set to thecurrent filename.</P><DL COMPACT><DT><CODE>$@</CODE><DD>This evaluates to the current target i.e. the name of the objectyou are currently trying to build. It is normal to use this as thefinal name of the program when compiling<DT><CODE>$?</CODE><DD>This is used only outside of suffix rules and means the name of all thefiles which must be compiled in order to build the current target.<PRE>target: file1.o file2.o<KBD>TAB</KBD> cc -o $@ $?</PRE><DT><CODE>$&#60;</CODE><DD>This is only used in suffix rules. It has the same meaning as <SAMP>`$?'</SAMP>but only in suffix rules. It stands for the pre-requisite, or the filewhich must be compiled in order to make a given object.<A NAME="IDX814"></A><A NAME="IDX815"></A><A NAME="IDX816"></A></DL><P>Note that, because <SAMP>`make'</SAMP> has some default rules defined in itsconfiguration file, a single-file C program can be compiledvery easily by typing <PRE>make filename.c</PRE><P>This is equivalent to<PRE>cc -c filename.ccc -o filename filename.o</PRE><P> <H3><A NAME="SEC168" HREF="unix_toc.html#TOC168">New suffix rules for C++</A></H3><P>Standard rules for C++ are not often built into UNIX systems at thetime of writing, but we can create them in our own Makefiles very easily.Here we shall use the GNU compiler g++'s conventions for C++ files. Here is a sample Makefile for using C++. Notethat the <SAMP>`.SUFFIXES'</SAMP> command must be used to declare new endingsor file extensions.<A NAME="IDX817"></A><A NAME="IDX818"></A></P><PRE>#################################################################### This is the Makefile for g++###################################################################OBJ = cpp-prog.o X.o Y.o Z.oCCPLUS = g++.SUFFIXES: .C .o .h ## Program Rules#filesys: ${OBJ}         $(CCPLUS) -o filesys $(OBJ)##  Extra dependencies on the header file# (if the header file changes, we need to rebuild *.o)#cpp-prog.o: filesys.hX.o: filesys.hY.o: filesys.hZ.o: filesys.h## Suffix rules#.C.o:          $(CCPLUS) -c $&#60;</PRE><P>The general rule here tells <CODE>make</CODE> that a <TT>`.o'</TT> filecan be created from a <TT>`.C'</TT> file by executing thecommand <SAMP>`$(CCPLUS) -c'</SAMP>. (This is identical to theC case, except for the name of the compiler). The extradependencies tell <CODE>make</CODE> that, if we change the headerfile <TT>`filesys.h'</TT>, then we must recompile all the fileswhich read in <TT>`filesys.h'</TT>, since this could affect all ofthese. Finally, the highest level rule says that to make<TT>`filesys'</TT> from the <TT>`.o'</TT> files, we have to run<SAMP>`$(CCPLUS) -o filesys *.o'</SAMP>.</P><P> <H2><A NAME="SEC169" HREF="unix_toc.html#TOC169">The <CODE>argv</CODE>, <CODE>argc</CODE> and <CODE>envp</CODE> parameters</A></H2><P>When we write C programs which reads command line arguments, they arefed to us as an array of strings called the argument vector.  Themechanisms for the C-shell and Perl are derived from the C argumentvector.  To read in the command line, we write<A NAME="IDX819"></A><A NAME="IDX820"></A><A NAME="IDX821"></A><A NAME="IDX822"></A><A NAME="IDX823"></A><A NAME="IDX824"></A></P><PRE>main (argc,argv,envp)int argc;char *argv[], *envp[];{printf ("The first argument was %s\n",argv[1]);}</PRE><P>Argument zero is the name of the program itself and <SAMP>`argv[argc-1]'</SAMP>is the last argument. The above definitions are in Kernighan and RitchieC style. In ANSI C, the arguments can be declared using prototype:</P><PRE>main (int argc, char **argv){}</PRE><P>The array of strings <SAMP>`envp[]'</SAMP> is a list of values of the<EM>environment variables</EM> of the system, formatted by<PRE>NAME=value</PRE><P>This gives C programmers access to the shell's global environment.</P><P> <H2><A NAME="SEC170" HREF="unix_toc.html#TOC170">Environment variables in C</A></H2><P><A NAME="IDX825"></A><A NAME="IDX826"></A><A NAME="IDX827"></A></P><P>In addition to the <SAMP>`envp'</SAMP> vector, it is possible to access theenvironment variables through the call <SAMP>`getenv()'</SAMP>. This is used asfollows; suppose we want to access the shell environment variable <SAMP>`$HOME'</SAMP>.<PRE>char *string;string = getenv("HOME");</PRE><P><SAMP>`string'</SAMP> is now a pointer to static but public data. You should notuse <SAMP>`string'</SAMP> as if it were you're own property because it will beused again by the system. Copy it's contents to another string beforeusing the data.<PRE>char buffer[500];strcpy (buffer,string);</PRE><P> <H2><A NAME="SEC171" HREF="unix_toc.html#TOC171">Files and directories</A></H2><P>All of the regular C functions from the standard library are availableto UNIX programmers. The standard functions only address the issueof reading and writing to files however, they do not deal with operatingsystem specific attributes such as file permissions and file types.Nor is there a mechanisms for obtaining lists of files within adirectory. The reason for these omissions is that they are operatingsystem dependent. To find out about these other attributes POSIX describessome standard UNIX system calls.</P><P> </P><H3><A NAME="SEC172" HREF="unix_toc.html#TOC172">opendir, readdir</A></H3><P><A NAME="IDX828"></A><A NAME="IDX829"></A><A NAME="IDX830"></A><A NAME="IDX831"></A></P><P>Files and directories are handled by functions defined in the headerfile <TT>`dirent.h'</TT>. In earlier UNIX systems the file <TT>`dir.h'</TT> wasused -- and the definitions were slightly different, but not much. Toget a list of files in a directory we must open the directory and readfrom it -- just like a file. (A directory is just a file which containsdata on its entries). The commands are<PRE>opendirclosedirreaddir</PRE><P>See the manual pages for dirent.  These functions return pointers to a<CODE>dirent</CODE> structure which is defined in the file<TT>`/usr/include/dirent.h'</TT>. Here is an example <CODE>ls</CODE> commandwhich lists the contents of the directory <TT>`/etc'</TT>. This headerdefines a structure</P><PRE>struct dirent    {   off_t                d_off;		/* offset of next disk dir entry */   unsigned long        d_fileno;	/* file number of entry */   unsigned short       d_reclen;	/* length of this record */   unsigned short       d_namlen;	/* length of string in d_name */   char	                d_name[255+1];	/* name (up to MAXNAMLEN + 1) */   };</PRE><P>which can be used to obtain information from the directory nodes.</P><PRE>#include &#60;stdio.h&#62;#include &#60;dirent.h&#62;main (){ DIR *dirh;  struct dirent *dirp;  static char mydir[20] = "/etc";  if ((dirh = opendir(mydir)) == NULL)   {   perror("opendir");   return;   }for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh))   {   printf("Got dir entry: %s\n",dirp-&#62;d_name);   }closedir(dirh);}</PRE><P>Notice that reading from a directory is like reading from a filewith <CODE>fgets()</CODE>,but the entries are filenames rather than lines of text.</P><P> <H3><A NAME="SEC173" HREF="unix_toc.html#TOC173"><CODE>stat()</CODE></A></H3><P><A NAME="IDX832"></A><A NAME="IDX833"></A><A NAME="IDX834"></A><A NAME="IDX835"></A></P><P>To determine the file properties or <EM>statistics</EM> we use thefunction call <SAMP>`stat()'</SAMP> or its corollary <SAMP>`lstat()'</SAMP>. Both thesefunctions find out information about files (permissions, owner, filetypeetc).  The only difference between them is the way in which they treatsymbolic links.  If <SAMP>`stat'</SAMP> is used on a symbolic link, it stats thefile the link points to rather than the link itself. If <SAMP>`lstat'</SAMP> isused, the data refer to the link.  Thus, to detect a link, we must use<SAMP>`lstat'</SAMP>, See section <A HREF="unix.html#SEC174">lstat and readlink</A>.</P><P>The data in the `stat' structure are defined in the file<TT>`/usr/include/sys/stat.h'</TT>.  Here are the most important structures.</P><PRE>struct	stat    {   dev_t        st_dev;             /* device number*/   ino_t        st_ino;             /* file inode */   mode_t       st_mode;            /* permission */   short        st_nlink;           /* Number of hardlinks to file */   uid_t        st_uid;             /* user id */   gid_t        st_gid;             /* group id */   dev_t        st_rdev;    off_t        st_size;            /* size in bytes */   time_t       st_atime;           /* time file last accessed */   time_t       st_mtime;           /* time file contents last modified */   time_t       st_ctime;           /* time last attribute change */   long         st_blksize;   long         st_blocks;   };</PRE><P> <H3><A NAME="SEC174" HREF="unix_toc.html#TOC174">lstat and readlink</A></H3><P><A NAME="IDX836"></A><A NAME="IDX837"></A><A NAME="IDX838"></A></P><P>The function <SAMP>`stat()'</SAMP> treats symbolic links as though theywere the files they point to. In other words, if we use <SAMP>`stat()'</SAMP>to read a symbolic link, we end up reading the file the link pointsto and not the link itself---we never see symbolic links. To avoid this problem, there is a differentversion of the stat function called <SAMP>`lstat()'</SAMP> which is identicalto <SAMP>`stat()'</SAMP> except that it treats links as links and <EM>not</EM> asthe files they point to. This means that we can test whether a file is asymbolic link, only if we use <SAMP>`lstat()'</SAMP>. (See the next paragraph.)</P><P>Once we have identified a file to be a symbolic link, we use the<SAMP>`readlink()'</SAMP> function to obtain the name of the file thelink points to.<PRE>#define bufsize 512char buffer[bufsize];readlink("/path/to/file",buffer,bufsize);</PRE><P>The result is returned in the string buffer.</P><P> <H2><A NAME="SEC175" HREF="unix_toc.html#TOC175"><CODE>stat()</CODE> test macros</A></H2><P><A NAME="IDX839"></A><A NAME="IDX840"></A><A NAME="IDX841"></A></P><P>As we have already mentioned, the UNIX mode bits contain not onlyinformation about what permissions a file has, but also bits describing thetype of file -- whether it is a directory or a link etc. There are macrosdefined in UNIX to extract this information from the <SAMP>`st_mode'</SAMP>member of the <SAMP>`stat'</SAMP> structure. They are defined in the <SAMP>`stat.h'</SAMP>headerfile. Here are some examples.</P><PRE>#define	S_ISBLK(m)    /* is block device */#define	S_ISCHR(m)    /* is character device */#define	S_ISDIR(m)    /* is directory */#define	S_ISFIFO(m)   /* is fifo pipe/socket */#define	S_ISREG(m)    /* is regular (normal) file */#define	S_ISLNK(m)    /* is symbolic link */  /* Not POSIX */#define	S_ISSOCK(m)   /* is a lock */#define	S_IRWXU 	/* rwx, owner */#define		S_IRUSR /* read permission, owner */#define		S_IWUSR /* write permission, owner */#define		S_IXUSR	/* execute/search permission, owner */#define	S_IRWXG		/* rwx, group */#define		S_IRGRP	/* read permission, group */#define		S_IWGRP	/* write permission, grougroup */#define		S_IXGRP	/* execute/search permission, group */#define	S_IRWXO		/* rwx, other */#define		S_IROTH	/* read permission, other */#define		S_IWOTH	/* write permission, other */#define		S_IXOTH	/* execute/search permission, other */</PRE><P>These return true or false when acting on the mode member.Here is an example See section <A HREF="unix.html#SEC176">Example filing program</A>.<PRE>struct stat statvar;stat("file",&#38;statvar); /* test return values */if (S_ISDIR(statvar.st_mode))   {   printf("Is a directory!");   }</PRE><P> </P><H3><A NAME="SEC176" HREF="unix_toc.html#TOC176">Example filing program</A></H3><P>The following example program demonstrates the use of the directoryfunctions in <CODE>dirent</CODE> and the <CODE>stat</CODE> function call.</P><PRE>/********************************************************************//*                                                                  *//* Reading directories and `statting' files                         *//*                                                                  *//********************************************************************/#include &#60;stdio.h&#62;#include &#60;dirent.h&#62;#include &#60;sys/types.h&#62;#include &#60;sys/stat.h&#62;#define DIRNAME "/."#define bufsize 255/********************************************************************/main (){ DIR *dirh;  struct dirent *dirp;  struct stat statbuf;  char *pathname[bufsize];  char *linkname[bufsize]; if ((dirh = opendir(DIRNAME)) == NULL)   {   perror("opendir");   exit(1);   } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh))   {   if (strcmp(".",dirp-&#62;d_name) == 0 || strcmp("..",dirp-&#62;d_name) == 0)      {      continue;      }    if (strcmp("lost+found",dirp-&#62;d_name) == 0)      {      continue;      }   sprintf(pathname,"%s/%s",DIRNAME,dirp-&#62;d_name);   if (lstat(pathname,&#38;statbuf) == -1)                /* see man stat */     {     perror("stat");     continue;     }   if (S_ISREG(statbuf.st_mode))      {      printf("%s is a regular file\n",pathname);      };   if (S_ISDIR(statbuf.st_mode))      {      printf("%s is a directory\n",pathname);      }   if (S_ISLNK(statbuf.st_mode))      {      bzero(linkname,bufsize);                         /* clear string */      readlink(pathname,linkname,bufsize);      printf("%s is a link to %s\n",pathname,linkname);      }   printf("The mode of %s is %o\n\n",pathname,statbuf.st_mode &#38; 07777);   }closedir(dirh);}</PRE><P> <H2><A NAME="SEC177" HREF="unix_toc.html#TOC177">Process control, <CODE>fork()</CODE>, <CODE>exec()</CODE>, <CODE>popen()</CODE> and system</A></H2><P>There is a number of ways in which processes can interact with oneanother and in which we can control their behaviour. We shall not gointo great detail in this course, only provide examples forreference. </P><P>The UNIX <SAMP>`fork()'</SAMP> function is used to create child processes.  This is the basis of all `heavyweight' multitasking under UNIX.Here is a simple example of fork in which we start a child processfrom within a program and wait for it to finish. Note thatthe code for the parent and the child is is the same file. Theonly thing that distinguishes parent from child is the valuereturned by the fork function.</P><P>When <SAMP>`fork()'</SAMP> is called, it duplicates the entire currentprocess so that two parallel processes are then running. The onlydifference between these is that the child process (the copy)gets a return value of zero from <SAMP>`fork()'</SAMP>, whereas theparent gets a return value equal to the process identifier(pid) of the child. This value can be used by the parentto send messages or to wait for the child. Here we show asimple example in which the <SAMP>`wait(NULL)'</SAMP> command is usedto wait for the last child spawned by the parent.</P><PRE>/**************************************************************//*                                                            *//*  A brief demo of the UNIX process duplicator fork().       *//*                                                            *//**************************************************************/#include &#60;stdio.h&#62;/***************************************************************/main (){ int pid, cid;pid = getpid();printf ("Fork demo! I am the parent (pid = %d)\n",pid);if (! fork())   {   cid = getpid();   printf ("I am the child (cid = %d) of (pid=%d)\n",cid,pid);   ChildProcess();   exit(0);   }printf("Parent waiting here for the child...\n");wait(NULL);printf("Child finished, parent quitting too!\n");}/**************************************************************/ChildProcess(){ int i;for (i = 0; i &#60; 10; i++)   {   printf ("%d...\n",i);   sleep(1);   }}</PRE><P>Another possibility is that we might want to execute a program andwait to find out what the result of the program is beforecontinuing. There are two ways to do this. The first is a variationon the theme above and uses <CODE>fork()</CODE>.</P><P>Let's create a function which runs a shell command from withina C program, and determines its return value. We make the result a boolean (integer) value, so that the function returns`true' if the shell command exits normally, See section <A HREF="unix.html#SEC84">Return codes</A>.</P><PRE>if (ShellCommandReturnsZero(<VAR>shell-command</VAR>))   {   printf ("Command %s went ok\n",<VAR>shell-command</VAR>);   }</PRE><P>To do this we first have to fork a new process and thenuse one of the <CODE>exec</CODE> commands to load a newcode image on top of the new process.<A NAME="IDX842"></A>shell commands from C This sounds complicated, but it is necessarybecause of the way UNIX handles processes.  If we had no use for thereturn value, we could simply execute a shell command using the<CODE>system("shell command")</CODE> function, (which does all this for us)but when <CODE>system()</CODE> exits, we can only tell if the command wasexecuted successfully or unsuccessfully--we learn nothing about whatactually failed (the shell or command which was executed under theshell?)  If we require detailed information about what happened to thechild process then we need to do the following.</P><PRE>#include &#60;sys/types.h&#62;#include &#60;sys/wait.h&#62;  /* Send complete command as a string */  /* including all arguments           */ShellCommandReturnsZero(comm)char *comm;{ int status, i, argc;  pid_t pid;  char arg[maxshellargs][bufsize];  char **argv;/* Build argument array for execv call*/for (i = 0; i &#60; maxshellargs; i++)   {   bzero (arg[i],bufsize);   }argc = SplitCommand(comm,arg);if ((pid = fork()) &#60; 0)   {   FatalError("Failed to fork new process");   }else if (pid == 0)                     /* child */   {   argv = malloc((argc+1)*sizeof(char *));   for (i = 0; i &#60; argc; i++)      {      argv[i] = arg[i];      }   argv[i] = (char *) NULL;   if (execv(arg[0],argv) == -1)      {      yyerror("script failed");      perror("execvp");      exit(1);      }   }else                                    /* parent */   {   if (wait(&#38;status) != pid)      {      printf("Wait for child failed\n");      perror("wait");      return false;      }   else      {      if (WIFSIGNALED(status))         {         printf("Script %s returned: %s\n",comm,WTERMSIG(status));         return false;         }      if (! WIFEXITED(status))         {         return false;         }      if (WEXITSTATUS(status) == 0)         {         return true;         }      else         {         return false;         }      }   }}/*******************************************************************/SplitCommand(comm,arg) char *comm, arg[maxshellargs][bufsize]; { char *sp;  int i = 0, j;  char buff[bufsize]; for (sp = comm; *sp != NULL; sp++)   {   bzero(buff,bufsize);    if (i &#62;= maxshellargs-1)      {      yyerror("Too many arguments in embedded script");      FatalError("Use a wrapper");      }    while (*sp == ' ' || *sp == '\t')      {      sp++;      }    switch (*sp)      {      case '\"': sscanf (++sp,"%[^\"]",buff);                 break;      case '\": sscanf (++sp,"%[^\']",buff);                 break;      default:   sscanf (sp,"%s",buff);                 break;      }    for (j = 0; j &#60; bufsize; j++)      {      arg[i][j] = buff[j];      }    sp += strlen(arg[i]);   i++;   }return (i);}</PRE><P>In this example, the script waits for the exit signal from the childprocess before continuing. The return value from the child isavailable from the wait function with the help of a set of macrosdefined in <TT>`/usr/include/sys/wait.h'</TT>. The value isgiven by <CODE>WTERMSIG(status)</CODE>.<A NAME="IDX843"></A><A NAME="IDX844"></A><A NAME="IDX845"></A></P><P>In the final example, we can open a pipe to aprocess directly in a C programas though it were a file, by using the function <CODE>popen()</CODE>.<A NAME="IDX846"></A><A NAME="IDX847"></A><A NAME="IDX848"></A>Pipes may be opened for reading or for writing, in exactly the sameway as a file is opened. The child process is automaticallysynchronized with the parent using this method. Here is a program which opens a UNIX command for reading (both stdout andstderr) from the child process are piped into the program.Notice that the syntax used in this call is that used bythe Bourne shell, since this is build deeply into the UNIXexecution design.</P><PRE>#define bufsize 1024FILE *pp;char VBUFF[bufsize];...if ((pp = popen( "/sbin/mount -va 2&#60;&#38;1","r")) == NULL)   {   printf("Failed to open pipe\n");   return errorcode;   } while (!feof(pp))   {   fgets(VBUFF,bufsize,pp);   /* Just write the output to stdout */   printf ("Pipe read: %s\n",VBUFF);   } pclose(pp);</PRE><P> <H2><A NAME="SEC178" HREF="unix_toc.html#TOC178">A more secure <CODE>popen()</CODE></A></H2><P>One problem with the <CODE>popen()</CODE> system call is that it uses ashell to execute the command it obtains a pipe to. In the past thishas been used to allow UNIX security breaches, using a so-called <CODE>IFS</CODE> attack which can trick the shell into executing a program withthe name of the first node in the directory of the executable. For instance,if the pipe was to open the program <TT>`/bin/ps'</TT>, this coudl be trickedinto executing a program in the current working directory of the processcalled <TT>`bin'</TT> with argument <SAMP>`ps'</SAMP>.</P><P>The solution is not to use a shell at all, but to replace <CODE>popen()</CODE>with a version which calls <CODE>exec()</CODE> directly. Here is a safeversion from the source code of cfengine:</P><PRE>#define bufsize      4096#define maxshellargs 20pid_t *CHILD;int    MAXFD = 20; /* Max number of simultaneous pipes *//***************************************************************/FILE *cfpopen(command, type)    char *command, *type; { char arg[maxshellargs][bufsize];   int i, argc, pd[2];   char **argv;   pid_t pid;   FILE *pp = NULL; if ((*type != 'r' &#38;&#38; *type != 'w') || (type[1] != '\0'))    {    errno = EINVAL;    return NULL;    }  if (CHILD == NULL)   /* first time */    {    if ((CHILD = calloc(MAXFD,sizeof(pid_t))) == NULL)       {       return NULL;       }    } if (pipe(pd) &#60; 0)  /* Create a pair of descriptors to this process */    {    return NULL;    } if ((pid = fork()) == -1)    {    return NULL;    }  if (pid == 0)    {    switch (*type)       {       case 'r':                 close(pd[0]);        /* Don't need output from parent */                 if (pd[1] != 1)                    {                    dup2(pd[1],1);    /* Attach pp=pd[1] to our stdout */                    dup2(pd[1],2);    /* Merge stdout/stderr */                    close(pd[1]);                    }                 break;       case 'w':                 close(pd[1]);                 if (pd[0] != 0)                    {                    dup2(pd[0],0);                    close(pd[0]);                   }       }    for (i = 0; i &#60; MAXFD; i++)       {       if (CHILD[i] &#62; 0)          {          close(CHILD[i]);          }       argc = SplitCommand(command,arg);       argv = (char **) malloc((argc+1)*sizeof(char *));       if (argv == NULL)          {          FatalError("Out of memory");          }              for (i = 0; i &#60; argc; i++)          {          argv[i] = arg[i];          }       argv[i] = (char *) NULL;       if (execv(arg[0],argv) == -1)          {          sprintf(OUTPUT,"Couldn't run %s",arg[0]);          CfLog(cferror,OUTPUT,"execv");          }       _exit(1);       }    } else    {    switch (*type)       {       case 'r':                 close(pd[1]);                       if ((pp = fdopen(pd[0],type)) == NULL)                    {                    return NULL;                    }                 break;             case 'w':                 close(pd[0]);                       if ((pp = fdopen(pd[1],type)) == NULL)                    {                    return NULL;                    }       }    CHILD[fileno(pp)] = pid;    return pp;    } }/***************************************************************/cfpclose(pp)FILE *pp;{ int fd, status;  pid_t pid;Debug("cfpclose(pp)\n");if (CHILD == NULL)  /* popen hasn't been called */   {   return -1;   }fd = fileno(pp);if ((pid = CHILD[fd]) == 0)   {   return -1;   }CHILD[fd] = 0;if (fclose(pp) == EOF)   {   return -1;   }Debug("cfpopen - Waiting for process %d\n",pid); #ifdef HAVE_WAITPIDwhile(waitpid(pid,&#38;status,0) &#60; 0)   {   if (errno != EINTR)      {      return -1;      }   }  return status;  #else       if (wait(&#38;status) != pid)    {    return -1;    } else    {    if (WIFSIGNALED(status))       {       return -1;       }        if (! WIFEXITED(status))       {       return -1;       }        return (WEXITSTATUS(status));    }#endif}/*******************************************************************//* Command exec aids                                               *//*******************************************************************/SplitCommand(comm,arg)char *comm, arg[maxshellargs][bufsize];{ char *sp;  int i = 0, j;  char buff[bufsize];for (sp = comm; sp &#60; comm+strlen(comm); sp++)   {   bzero(buff,bufsize);   if (i &#62;= maxshellargs-1)      {      CfLog(cferror,"Too many arguments in embedded script","");      FatalError("Use a wrapper");      }   while (*sp == ' ' || *sp == '\t')      {      sp++;      }   switch (*sp)      {      case '\0': return(i-1);      case '\"': sscanf (++sp,"%[^\"]",arg[i]);                 break;      case '\": sscanf (++sp,"%[^\']",arg[i]);                 break;      case '`':  sscanf (++sp,"%[^`]",arg[i]);                 break;      default:   sscanf (sp,"%s",arg[i]);                 break;      }   sp += strlen(arg[i]);   i++;   }return (i);}</PRE><P> <H2><A NAME="SEC179" HREF="unix_toc.html#TOC179">Traps and signals</A></H2><P>Processes can receive signals from the UNIX kernel at any time.Some of these signals terminate the execution of the program.This can cause problems if the program is in the middle of criticalactivity such as writing to a file. For that reason we can trapsignals and provide our own routine for handling them in a special way.</P><P>A signal handler is made by calling the function <SAMP>`signal()'</SAMP> foreach signal and by specifying a pointer to a function which will becalled in the event of a signal. For example:<PRE>main (){ int HandleSignal();signal(SIGTERM,HandleSignal);}HandleSignal(){/* Tidy up and exit cleanly */exit(0);}</PRE><P><SAMP>`SIGTERM'</SAMP> is the usual signal sent by the command <SAMP>`kill'</SAMP>. There aremany other signals which can be sent to programs. Here is list.You have to decide for yourself whether or not you want toprovide your own signal handling function.To ignore a signal, you write<PRE>signal(SIG<VAR>type</VAR>,SIG_IGN);</PRE><P>To remove a signal handler and re-activate a signal, you write<PRE>signal(SIG<VAR>type</VAR>,SIG_DFL);</PRE><P> <H2><A NAME="SEC180" HREF="unix_toc.html#TOC180">Regular expressions</A></H2><P>A regular expression is a pattern for matching strings of text.We have met regular expressions earlier in connection with theshell and Perl. Naturally these earlier encounters have theirroots in C functions for handling expressions. A regularexpression is used by first `compiling' it into a convenientdata structure. Then a matching function is used to compare theexpression with a test string. In this example program we showhow a regular expression typed in as an argument to the programis found within strings of input entered on the keyboard.</P><PRE>#include &#60;stdio.h&#62;#include &#60;regex.h&#62;main (argc,argv)int argc;char **argv;{ char buffer[1024]; regex_t rx; regmatch_t match; size_t nmatch = 1; if (regcomp(&#38;rx, argv[1], REG_EXTENDED) != 0)    {    perror("regcomp");    return;    } while (!feof(stdin))    {    fgets(buffer,1024,stdin);        if (regexec(&#38;rx,buffer,1,&#38;match,0) == 0)       {       printf("Matched:(%s) at %d to %d",buffer,match.rm_so,match.rm_eo);       }    }regfree(&#38;rx);}</PRE><P>Here is an example of its use. Theoutput of the program is in <EM>italics</EM> </P><PRE>% a.out xyzthis is a stringanother stringan xyz string<EM>Matched: (an xyz string) at 3 to 6</EM>another xyz zyxxyz string<EM>Matched: (another xyz xyz string) at 8 to 11</EM>% a.out 'xyz|abc'This is a stringAn abc string<EM>Matched: (An abc string) at 3 to 6</EM>Or an xyz string<EM>Matched: (Or an xyz string) at 6 to 9</EM></PRE><P>If you don't want the match data set <CODE>&#38;pm</CODE> to <CODE>NULL</CODE>. To getan exact match rather than a substring check that the bounds are 0 and<CODE>strlen(argv[1])-1</CODE>.</P><P> <H2><A NAME="SEC181" HREF="unix_toc.html#TOC181">DES encryption</A></H2><P>Encryption with the SSLeay library, compile with command</P><PRE>  gcc crypto.c -I/usr/local/ssl/include -L/usr/local/ssl/lib -lcrypto</PRE><P>Example of normal triple DES encryption which works only on an 8-bytebuffer:<PRE>/*****************************************************************************//*                                                                           *//* File: crypto.c                                                            *//*                                                                           *//* Compile with:  gcc program.c  -lcrypto   (SSLeay)                         *//*                                                                           *//*****************************************************************************/#include &#60;stdio.h&#62;#include &#60;des.h&#62;#define bufsize 1024    /* Note how this truncates to 8 characters */main (){ char in[bufsize],out[bufsize],back[bufsize];  des_cblock key1,key2,key3,seed = {0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10};  des_key_schedule ks1,ks2,ks3;strcpy(in,"1 2 3 4 5 6 7 8 9 a b c d e f g h i j k");des_random_seed(seed);des_random_key(key1);des_random_key(key2);des_random_key(key3); des_set_key((C_Block *)key1,ks1);des_set_key((C_Block *)key2,ks2);des_set_key((C_Block *)key3,ks3);des_ecb3_encrypt((C_Block *)in,(C_Block *)out,ks1,ks2,ks3,DES_ENCRYPT);printf("Encrypted [%s] into [%s]\n",in,out);des_ecb3_encrypt((C_Block *)out,(C_Block *)back,ks1,ks2,ks3,DES_DECRYPT);printf("and back to.. [%s]\n",back); }</PRE><P>Triple DES, chaining mode, for longer strings (which must be a multiple of8 bytes):<PRE>/*****************************************************************************//*                                                                           *//* File: crypto.c                                                            *//*                                                                           *//* Compile with:  gcc program.c  -lcrypto   (SSLeay)                         *//*                                                                           *//*****************************************************************************/#include &#60;stdio.h&#62;#include &#60;des.h&#62;#define bufsize 1024    /* This can be used on arbitrary length buffers */main (){ char in[bufsize],out[bufsize],back[bufsize],workvec[bufsize];  des_cblock key1,key2,key3,seed = {0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10};  des_key_schedule ks1,ks2,ks3;strcpy(in,"1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z");des_random_seed(seed);des_random_key(key1);des_random_key(key2);des_random_key(key3); des_set_key((C_Block *)key1,ks1);des_set_key((C_Block *)key2,ks2);des_set_key((C_Block *)key3,ks3);/* This work vector can be intialized t anything ...*/memset(workvec,0,bufsize);des_ede3_cbc_encrypt((C_Block *)in,(C_Block *)out,(long)strlen(in),           ks1,ks2,ks3,(C_Block *)workvec,DES_ENCRYPT);printf("Encypted [%s] into [something]\n",in);/* .. but this must be initialized the same as above */memset(workvec,0,bufsize);/* Note that the length is the original length, not strlen(out) */des_ede3_cbc_encrypt((C_Block *)out,(C_Block *)back,(long)strlen(in),           ks1,ks2,ks3,(C_Block *)workvec,DES_DECRYPT);printf("and back to.. [%s]\n",back); }</PRE><P> <H2><A NAME="SEC182" HREF="unix_toc.html#TOC182">Device control: ioctl</A></H2><P><A NAME="IDX849"></A><A NAME="IDX850"></A></P><P>The C function <SAMP>`ioctl'</SAMP> (I/O control) is used to send specialcontrol commands to devices like the disk and the network interface.The syntax of the function is<PRE>int ioctl(fd, request, arg)int fd, request;long arg;</PRE><P>The first parameter is normally as device handle or socket descriptor.The second is a control parameter. Lists of valid control parameters arenormally defined in the system `include' files for a particulardevice. They are device and system dependent so you need a local manualand som detective work to find out what they are. The final parameter is a pointer to a variable whichreceives return data from the device.</P><P><SAMP>`ioctl'</SAMP> commands are device specific, by their nature. The commandsfor the ethernet interface device are only partially standardized, forexample.  We could read the ethernet device (which is called `le0' on aSun workstation), using the following command:<PRE># include &#60;sys/socket.h&#62;      /* Typical includes for internet */# include &#60;sys/ioctl.h&#62;# include &#60;net/if.h&#62;# include &#60;netinet/in.h&#62;# include &#60;arpa/inet.h&#62;# include &#60;netdb.h&#62;# include &#60;sys/protosw.h&#62;# include &#60;net/route.h&#62;struct ifreq IFR;int sk;struct sockaddr_in sin;strcpy(IFR.ifr_name,"le0");IFR.ifr_addr.sa_family = AF_INET;if ((sk = socket(AF_INET,SOCK_DGRAM,IPPROTO_IP)) == -1)   {   perror("socket");   exit(1);   }if (ioctl(sk,SIOCGIFFLAGS, (caddr_t) &#38;IFR) == -1)    {   perror ("ioctl");   exit(1);   }</PRE><P>We shall not go into the further details of <SAMP>`ioctl'</SAMP>, but simply noteits role in system programming.</P><P> <H2><A NAME="SEC183" HREF="unix_toc.html#TOC183">Database example (Berkeley db)</A></H2><PRE>DBT key,value;DB *dbp;DBC *dbcp;db_recno_t recno;if ((errno = db_open(CHECKSUMDB,DB_BTREE, DB_CREATE, 0664, NULL, NULL, &#38;dbp)) != 0)   {   sprintf(OUTPUT,"cfd: couldn't open checksum database %s\n",CHECKSUMDB);   CfLog(cferror,OUTPUT,"db_open");   return false;   } bzero(&#38;value,sizeof(value)); bzero(&#38;key,sizeof(key));             key.data = filename;key.size = strlen(filename)+1;value.data = dbvalue;value.size = sizeof(dbvalue);    if ((errno = dbp-&#62;del(dbp,NULL,&#38;key,0)) != 0)   {   CfLog(cferror,"","db_store");   }  key.data = filename;key.size = strlen(filename)+1;   if ((errno = dbp-&#62;put(dbp,NULL,&#38;key,&#38;value,0)) != 0)   {   CfLog(cferror,"put failed","db-&#62;put");   }      if ((errno = dbp-&#62;get(dbp,NULL,&#38;key,&#38;value,0)) == 0)   {   /* Not found ... */   return;   }dbp-&#62;close(dbp,0);</PRE><P> <H2><A NAME="SEC184" HREF="unix_toc.html#TOC184">Text parsing tools: <SAMP>`lex'</SAMP> and <SAMP>`yacc'</SAMP></A></H2><P><A NAME="IDX851"></A><A NAME="IDX852"></A><A NAME="IDX853"></A></P><P><EM>This section is a taster only. You only need to know what lex andyacc are, not how they work.</EM></P><P><SAMP>`lex'</SAMP> and <SAMP>`yacc'</SAMP> are two tools for the C programmer who wishesto make a text parser. A text parser is a program which reads a text fileand interprets the symbols in it. Every programming language mustinclude a text parser, for instance.</P><P>The <SAMP>`yacc'</SAMP> (yet another compiler compiler) program generates Ccode which parses a textfile, given a description of the syntaxrules for the file. In other words, we define the logical structureof the text file, according to the way we wish to interpret itand give the rules to <SAMP>`yacc'</SAMP>. <SAMP>`yacc'</SAMP> produces C codefrom this which does the job.</P><P><SAMP>`lex'</SAMP> is a `lexer'. It is normally used together with <SAMP>`yacc'</SAMP>. <SAMP>`lex'</SAMP> <EM>tokenizes</EM> or identifies symbols ina file. What that means is that it reads in a file and matches<EM>types</EM> of string in the file which are defined in terms ofregular expressions by the programmer, and returns symbolicvalues for those strings.</P><P>Although <SAMP>`lex'</SAMP> can be used by independently of <SAMP>`yacc'</SAMP>, itis normally used to identify the different <EM>types</EM> of string whichdefine the syntax of a file. For example, suppose <SAMP>`yacc'</SAMP> was parsing a C program. On the beginning of a line, itmight expect to find either a variable name or a preprocessor symbol.A variable name is just a string consisting of characters fromthe set <SAMP>`0-9a-Z_'</SAMP>, whereas a preprocessor command always starts with the character <SAMP>`#'</SAMP>. <SAMP>`yacc'</SAMP> passes control to <SAMP>`lex'</SAMP>which reads the file and matches the first object on the line.If it finds a variable, it returns to <SAMP>`yacc'</SAMP> a <EM>token</EM> which is a number or valuecorresponding to `variable'. Similarly, if it finds a preprocessorcommand, it returns a token for that. If it doesn't match eithertype it returns something else and <SAMP>`yacc'</SAMP> signals a syntax error.</P><P>Here is a <SAMP>`yacc'</SAMP> file which parses a file consisting of lines of the forma+b, where $a$ and $b$ are numbers -- any other syntax is incorrect.We could have used this later in the exampleprogram for the client-server example, See section <A HREF="unix.html#SEC187">Socket streams</A>.</P><P>You can learn more about lex and yacc in <EM>"Lex and Yacc", J. Levine,T. Mason and D. Brown, O'Reilly and Assoc.</EM></P><PRE>%{/*******************************************************************//*                                                                 *//*  PARSER for a + b protocol                                      *//*                                                                 *//* The section between the single %'s gets copied verbatim into    *//* the resulting C code yacc generates -- including this comment!  *//*                                                                 *//*******************************************************************/#include &#60;stdio.h&#62;extern char *yytext;%}%token NUMBER PLUS%%specification:       { yyerror("Warning: invalid statement");}                     | statement;statement:            NUMBER PLUS NUMBER;</PRE><P>The lexer to go with this parser generates the tokens NUMBER and PLUSused by <SAMP>`yacc'</SAMP>:</P><PRE>%{/*******************************************************************//*                                                                 *//*  LEXER for a + b protocol                                       *//*                                                                 *//* Returns token types NUMBER and PLUS to yacc, one at a time      *//*                                                                 *//*******************************************************************/#include "y.tab.h"       /* yacc produces this -- need this line! */%}number    [0-9]+plus      [+]%%number                 {                       return NUMBER;                       }plus                   {                       return PLUS;                       }.                      {                       return yytext[0];                       }%%/* EOF */</PRE><P>The main program which uses <SAMP>`yacc'</SAMP> and <SAMP>`lex'</SAMP> looks like this:</P><PRE>extern FILE *yyin;main (){if ((yyin = fopen("My_Input_File","r")) == NULL)      /* Open file */   {   printf("Can't open file\n");   exit (1);   }while (!feof(yyin))   {    yyparse();   }fclose (yyin);}</PRE><P> <H2><A NAME="SEC185" HREF="unix_toc.html#TOC185">Exercises</A></H2><OL><LI>Write a daemon program with a signal handler which makes a logof the heaviest (maximum cpu) process running, every five minutes. Theprogram should exit if the log file becomes greater than 5-kbytes.<LI>Rewrite in C the perl program which lists all the files inthe current directory containing a certain string.<LI>Write a version of `more' which prints control characters safely.See the <SAMP>`cat -e'</SAMP> command.<LI>Write a Makefile to create a shared library from a number of object files.</OL><H1><A NAME="SEC186" HREF="unix_toc.html#TOC186">Network Programming</A></H1><P>Client-server communication is the basis of modern operating systemtechnology. The UNIX socket mechanism makes stream-based communicationvirtually transparent.</P><P> </P><H2><A NAME="SEC187" HREF="unix_toc.html#TOC187">Socket streams</A></H2><P>Analogous to filestreams are <EM>sockets</EM> or TCP/IP <EM>networkconnections</EM>. A socket is a two-way (read/write) pseudo-file node. Anopen socket stream is like an open file-descriptor.  Berkeley socketsare part of the standard C library.</P><P>There are two main kinds of socket: TCP/IP sockets and UNIX domainsockets.  UNIX sockets can be used to provide local interprocesscommunication using a filestream communication protocol. TCP/IP socketsopen file descriptors across the network.<A NAME="IDX854"></A><A NAME="IDX855"></A><A NAME="IDX856"></A>A TCP/IP socket isa file stream associated with an IP address and a port number.We write to a socket descriptor just as with a file descriptor, eitherwith <CODE>write()</CODE> or using <CODE>send()</CODE>.</P><P>When sending binary data over a network we have to be careful aboutmachine level representations of data.Operating systems (actually the hardware they run on) fall intotwo categories known as <EM>big endian</EM> and <EM>little endian</EM>. Thenames refer to the <EM>byte-order</EM> of numerical representations.<A NAME="IDX857"></A><A NAME="IDX858"></A><A NAME="IDX859"></A><A NAME="IDX860"></A>The names indicate how large integers (which require say 32 bits or more)are stored in memory. Little endian systems store the least significant bytefirst, while big endian systems store the most significant byte first.For example, the representation of the number 34,677,374 has either ofthese forms.</P><PRE>          -----------------------------------  Big    |   2    |   17   |  34    |   126  |          -----------------------------------          -----------------------------------  Little |   126  |   34   |  17    |   2    |          -----------------------------------</PRE><P>Obviously if we are transferring data from one host to another, bothhosts have to agree on the data representation otherwise there would bedisastrous consequences. This means that there has to be a commonstandard of <EM>network byte ordering</EM>.  For example, Solaris (SPARChardware) uses network byte ordering (big endian), while GNU/Linux(Intel hardware) uses the opposite (little endian). This means thatIntel systems have to convert the format every time something istransmitted over the network. UNIX systems provide generic functionsfor converting between host-byteorder and network-byteorder for smalland long integer data:<PRE>   htonl,  htons,  ntohl, ntohs</PRE><P>Here we list two example programs which show how to make a client-serverpair.  The server enters a loop, and listens for connections from anyclients (the generic address <SAMP>`INADDR_ANY'</SAMP> is a wildcard for anyaddress on the current local network segment). The client program sendsrequests to the server as a protocol in the form of a string of the type<SAMP>`a + b'</SAMP>. Normally <SAMP>`a'</SAMP> and <SAMP>`b'</SAMP> are numbers, in which casethe server returns their sum to the client.  If the message has thespecial form <SAMP>`halt + *'</SAMP>, where the star is arbitrary, then theserver shuts down. Any other form of message results in an error, whichthe server signals to the client.</P><P>The basic structure of the client-server components in terms ofsystem calls is this:</P><PRE>Client:  socket()             <VAR>Create a socket</VAR>  connect()            <VAR>Contact a server socket (IP + port)</VAR>    while (?)       {       send()          <VAR>Send to server</VAR>       recv()          <VAR>Receive from server</VAR>       }Server:   socket()            <VAR>Create a socket</VAR>   bind()              <VAR>Associates the socket with a fixed address</VAR>   listen()            <VAR>Create a listen queue</VAR>   while()      {      reply=accept()   <VAR>Accept a connection request</VAR>      recv()           <VAR>Receive from client</VAR>      send()           <VAR>Send to client</VAR>      }</PRE><P> <PRE>/**********************************************************************//*                                                                    *//* The client part of a client-server pair. This simply takes two     *//* numbers and adds them together, returning the result to the client *//*                                                                    *//* Compiled with:                                                     *//*                   cc server.c                                      *//*                                                                    *//* User types:                                                        *//*                   3 + 5                                            *//*                   a + b                                            *//*                   halt + server                                    *//**********************************************************************/#include &#60;stdio.h&#62;#include &#60;sys/types.h&#62;#include &#60;sys/socket.h&#62;#include &#60;netinet/in.h&#62;#include &#60;netdb.h&#62;#define PORT 9000                   /* Arbitrary non-reserved port */#define HOST "nexus.iu.hio.no"#define bufsize 20/**********************************************************************//* Main                                                               *//**********************************************************************/main (argc,argv)int argc;char *argv[];{ struct sockaddr_in cin;   struct hostent *hp;  char buffer[bufsize];  int sd;if (argc != 4)   {   printf("syntax: client a + b\n");   exit(1);   }<A NAME="IDX861"></A>if ((hp = gethostbyname(HOST)) == NULL)   {   perror("gethostbyname: ");   exit(1);   }memset(&#38;cin,0,sizeof(cin));             /* Another way to zero memory */cin.sin_family = AF_INET;cin.sin_addr.s_addr = ((struct in_addr *)(hp-&#62;h_addr))-&#62;s_addr;cin.sin_port = htons(PORT);printf("Trying to connect to %s = %s\n",HOST,inet_ntoa(cin.sin_addr));<A NAME="IDX862"></A>if ((sd = socket(AF_INET,SOCK_STREAM,0)) == -1)   {   perror("socket");   exit(1);   }<A NAME="IDX863"></A>if (connect(sd,&#38;cin,sizeof(cin)) == -1)   {   perror("connect");   exit(1);   }sprintf(buffer,"%s + %s",argv[1],argv[3]);<A NAME="IDX864"></A>if (send(sd,buffer,strlen(buffer),0) == -1)   {   perror ("send");   exit(1);   }<A NAME="IDX865"></A>if (recv(sd,buffer,bufsize,0) == -1)   {   perror("recv");   exit (1);   }printf ("Server responded with %s\n",buffer);close (sd);unlink("./socket");}</PRE><PRE>/**********************************************************************//*                                                                    *//* The server part of a client-server pair. This simply takes two     *//* numbers and adds them together, returning the result to the client *//*                                                                    *//* Compiled with:                                                     *//*                   cc server.c                                      *//*                                                                    *//**********************************************************************/#include &#60;stdio.h&#62;#include &#60;sys/types.h&#62;#include &#60;sys/socket.h&#62;#include &#60;netinet/in.h&#62;#include &#60;netdb.h&#62;#define PORT 9000#define bufsize 20#define queuesize 5#define true 1#define false 0/**********************************************************************//* Main                                                               *//**********************************************************************/main (){ struct sockaddr_in cin;   struct sockaddr_in sin;  struct hostent *hp;  char buffer[bufsize];  int sd, sd_client, addrlen;memset(&#38;sin,0,sizeof(sin));       /* Another way to zero memory */sin.sin_family = AF_INET;sin.sin_addr.s_addr = INADDR_ANY;          /* Broadcast address */sin.sin_port = htons(PORT);if ((sd = socket(AF_INET,SOCK_STREAM,0)) == -1)   {   perror("socket");   exit(1);   }<A NAME="IDX866"></A>if (bind(sd,&#38;sin,sizeof(sin)) == -1)  /* Must have this on server */   {   perror("bind");   exit(1);   }<A NAME="IDX867"></A>if (listen(sd,queuesize) == -1)   {   perror("listen");   exit(1);   }<A NAME="IDX868"></A>while (true)  {  if ((sd_client = accept(sd,&#38;cin,&#38;addrlen)) == -1)      {      perror("accept");      exit(1);      }   if (recv(sd_client,buffer,sizeof(buffer),0) == -1)      {      perror("recv");      exit(1);      }   if (!DoService(buffer))      {      break;      }   if (send(sd_client,buffer,strlen(buffer),0) == -1)      {      perror("send");      exit(1);      }   close (sd_client);   }close (sd);printf("Server closing down...\n");}/**************************************************************/DoService(buffer)char *buffer;  /* This is the protocol section. Here we must */  /* check that the incoming data are sensible  */{ int a=0,b=0;printf("Received: %s\n",buffer);sscanf(buffer,"%d + %d\n",&#38;a,&#38;b);if (a &#62; 0 &#38;&#38; b&#62; 0)   {   sprintf(buffer,"%d + %d = %d",a,b,a+b);   return true;   }else   {   if (strncmp("halt",buffer,4) == 0)     {     sprintf(buffer,"Server closing down!");     return false;     }   else     {     sprintf(buffer,"Invalid protocol");     return true;     }   }}</PRE><P>In the example we use `streams' to implement a typical input/outputbehaviour for C. A stream interface is a so-called reliable protocol.<A NAME="IDX869"></A>There are other kinds of sockets too, called <EM>unrealiable</EM>, or UDPsockets.  Features to notice on the server are that we must bind to aspecific address. The client is always implicitly bound to an addresssince a socket connection always originates from the machine on whichthe client is running. On the server however we want to know whichaddresses we shall be receiving requests from. In the above example weuse the generic wildcard address <SAMP>`INADDR_ANY'</SAMP> which means that anyhost can connect to the server. Had we been more specific, we could havelimited communication to two machines only.</P><P>By calling <SAMP>`listen()'</SAMP> we set up a queue for incoming connections.Rather than forking a separate process to handle each request weset up a queue of a certain depth. If we exceed this depth thennew clients rtying to connect will be refused connection.</P><P>The <SAMP>`accept'</SAMP> call is the mechanism which extracts a `reply handle'from the socket. Using the handle obtained from this call we can replyto the client without having to open a special socket explicitly.</P><P>An improved server side connection can be setup, reading theservice name from <TT>`/etc/services'</TT> and setting reusablesocket options to avoid busy signals, like this:<PRE>  struct sockaddr_in cin, sin;   struct servent *server;  int sd, addrlen = sizeof(cin);  int portnumber, yes=1;  if ((server = getservbyname(<VAR>service-name</VAR>,"tcp")) == NULL)      {      CfLog(cferror,"Couldn't get cfengine service","getservbyname");      exit (1);      }      bzero(&#38;cin,sizeof(cin));    /*  Service returns network byte order */   sin.sin_port = (unsigned short)(server-&#62;s_port);   sin.sin_addr.s_addr = INADDR_ANY;   sin.sin_family = AF_INET;       if ((sd = socket(AF_INET,SOCK_STREAM,0)) == -1)      {      CfLog(cferror,"Couldn't open socket","socket");      exit (1);      }      if (setsockopt (sd, SOL_SOCKET, SO_REUSEADDR,                       (char *) &#38;yes, sizeof (int)) == -1)      {      CfLog(cferror,"Couldn't set socket options","sockopt");      exit (1);      }         if (bind(sd,(struct sockaddr *)&#38;sin,sizeof(sin)) == -1)      {           } /* etc */</PRE><P> <H2><A NAME="SEC188" HREF="unix_toc.html#TOC188">Multithreading a server</A></H2><P>All the arguments must be collected into a struct, since onlyone argument pointer can be sent to the pthread functions.</P><PRE>#include &#60;pthread.h&#62;SpawnCfGetFile(args)struct cfd_thread_arg *args;{ pthread_t tid;  void *CfGetFile();pthread_attr_init(&#38;PTHREADDEFAULTS);pthread_attr_setdetachstate(&#38;PTHREADDEFAULTS,PTHREAD_CREATE_DETACHED);   if (pthread_create(&#38;tid,&#38;PTHREADDEFAULTS,CfGetFile,args) != 0)   {   CfLog(cferror,"pthread_create failed","create");   CfGetFile(args);   }   pthread_attr_destroy(&#38;PTHREADDEFAULTS);}/***************************************************************/void *CfGetFile(args)struct cfd_thread_arg *args;{ pthread_mutex_t mutex;if (pthread_mutex_lock(&#38;mutex) != 0)   {   CfLog(cferror,"pthread_mutex_lock failed","pthread_mutex_lock");   free(args-&#62;replyfile);  /* from strdup in each thread */   DeleteConn(args-&#62;connect);   free((char *)args);   return NULL;   }ACTIVE_THREADS++;   /* Global variable */if (pthread_mutex_unlock(&#38;mutex) != 0)   {   CfLog(cferror,"pthread_mutex_unlock failed","unlock");   }   /* send data */ if (pthread_mutex_lock(&#38;mutex) != 0)   {   CfLog(cferror,"pthread_mutex_lock failed","pthread_mutex_lock");   return;   } ACTIVE_THREADS--;   if (pthread_mutex_unlock(&#38;mutex) != 0)   {   CfLog(cferror,"pthread_mutex_unlock failed","unlock");   }#endif return NULL;}</PRE><P> <H2><A NAME="SEC189" HREF="unix_toc.html#TOC189">System databases</A></H2><P><A NAME="IDX870"></A><A NAME="IDX871"></A><A NAME="IDX872"></A><A NAME="IDX873"></A></P><P>The C library calls which query the databases are, amongst others,<PRE>getpwnam            <VAR>get password data by name</VAR>getpwuid            <VAR>get password data by uid</VAR>getgrnam            <VAR>get group data by name</VAR>gethostent          <VAR>get entry in hosts database</VAR>getnetgrent         <VAR>get entry in netgroups database</VAR>getservbyname       <VAR>get servive by name</VAR>getservbyport       <VAR>get service by port</VAR>get protobyname     <VAR>get protocol by name</VAR></PRE><P>For a complete list and how to use these, see the UNIX manual.<A NAME="IDX874"></A><A NAME="IDX875"></A><A NAME="IDX876"></A><A NAME="IDX877"></A><A NAME="IDX878"></A><A NAME="IDX879"></A><A NAME="IDX880"></A></P><P>The following example shows how to read the password file of thesystem. The functions used here can be used regardless of whetherthe network information service (NIS) is in use. The data arereturned in a structure which is defined in <SAMP>`/usr/include/pwd.h'</SAMP>.</P><PRE>/******************************************************************//*                                                                *//* Read the passwd file by name and sequentially                  *//*                                                                *//******************************************************************/#include &#60;unistd.h&#62;#include &#60;pwd.h&#62;main (){ uid_t uid;   struct passwd *pw;uid = getuid();pw = getpwuid(uid);printf ("Your login name is %s\n",pw-&#62;pw_name);printf ("Now here comes the whole file!\n\n");setpwent(); while (getpwent())   {   printf ("%s:%s:%s\n",pw-&#62;pw_name,pw-&#62;pw_gecos,pw-&#62;pw_dir);   }                   endpwent();}</PRE><P> <H2><A NAME="SEC190" HREF="unix_toc.html#TOC190">DNS - The Domain Name Service</A></H2><P><A NAME="IDX881"></A><A NAME="IDX882"></A><A NAME="IDX883"></A><A NAME="IDX884"></A>The second network database service is that which converts host anddomain names into IP numbers and vice versa. This is the domainname service, usually implemented by the BIND (Berkeley Internet Name Domain) software.The information here concerns version 4.9 of this software.</P><P> </P><H3><A NAME="SEC191" HREF="unix_toc.html#TOC191">gethostbyname()</A></H3><P>This is perhaps the most important function form hostnamelookup. <SAMP>`gethostbyname()'</SAMP> gets its information either from files,NIS or DNS. Its behaviour is configured by the files mentioned above,See section <A HREF="unix.html#SEC190">DNS - The Domain Name Service</A>.  It is used to look up the IP address of a named host(including domain name if DNS is used).  On the configurable systemsdescribed above, the full list of servers is queried until a reply isobtained.  The order in which the different services are queried isimportant here since DNS returns a <EM>fully qualified name</EM><A NAME="IDX885"></A>(host name plus domain name) whereas NIS and the <TT>`/etc/hosts'</TT> filedatabase return only a hostname.</P><P>gethostbyname returns data in the form of a pointer to a staticdata structure. The syntax is<PRE>#include &#60;netdb.h&#62;<A NAME="IDX886"></A>struct hostent *hp;hp = gethostbyname("myhost.domain.country")</PRE><P>The resulting structure varies on different implementationsof UNIX, but the `old BSD standard' is of the form:<PRE>struct  hostent    {   char    *h_name;        /* official name of host */   char    **h_aliases;    /* alias list */   int     h_addrtype;     /* host address type */   int     h_length;       /* length of address */   char    **h_addr_list;  /* list of addresses from name server */   };#define h_addr  h_addr_list[0]  /* address, for backward compatiblity */</PRE><P>The structure contains a list of addresses and or aliases from thenameserver. The interesting quantity is usually extracted by meansof the macro <SAMP>`h_addr'</SAMP>whcih gives the first value in the address list, though officially one should examine the whole list now.</P><P>This value is a pointer which can be converted into a text formby the following hideous type transformation:<PRE>#include &#60;sys/types.h&#62;#include &#60;sys/socket.h&#62;#include &#60;netinet/in.h&#62;struct sockaddr_in sin;cin.sin_addr.s_addr = ((struct in_addr *)(hp-&#62;h_addr))-&#62;s_addr;printf("IP address = %s\n",inet_ntoa(cin.sin_addr));</PRE><P>See the client program in the first section of this chapter for anexample of its use.</P><P> <H2><A NAME="SEC192" HREF="unix_toc.html#TOC192">C support for NFS</A></H2><P>The support for NFS mounting in the standard C library is throughtwo sources. NFS is based on the Sun's RPC system, so the basiccalls are only instances of standard RPC protocols.</P><P><A NAME="IDX887"></A>The C functions in the standard input/output library can be used toaccess NFS filesystems.  Since NFS imitates the UNIX filesystem asclosely as possible, NFS filesystems can be mounted in exactly the sameway as ordinary filesystems. Unfortunately, the C functions whichperform the mount operation in UNIX and depressingly non-standard. Theydiffer on almost every implementation of UNIX.</P><P>The basic function which mounts a filesystem, in <SAMP>`mount'</SAMP> (see<KBD>man (2) mount</KBD>). The mount table is stored in a file<EM>/etc/mtab</EM> on BSD systems (again the name varies wildly from UNIXto UNIX, mnttab on HPUX for instance).  The file <EM>/etc/rmtab</EM> on anNFS server contains a list of remote-mounted filesystems which aremounted by remote clients.  C functions exist which can read thefilesystem tables and place the resulting data in C struct types. Alas,these struct defintions are also quite different on differentsystems. See <TT>`/usr/include/sys/mount.h'</TT>, so the user wishing towrite system-independent code is confounded at the lowest level.</P><P> <H2><A NAME="SEC193" HREF="unix_toc.html#TOC193">Exercises</A></H2><OL><LI>Use <SAMP>`gethostbyname()'</SAMP> to make a simple program like <SAMP>`nslookup'</SAMP>which gives the internet address of a named host.<LI>Modify the client server example above to make a `remote ls'command called <SAMP>`rls'</SAMP>. You should be able to use the syntax<PRE>rls (options) hostname:/path/to/file </PRE></OL><H1><A NAME="SEC194" HREF="unix_toc.html#TOC194">Summary of programming idioms.</A></H1><DL COMPACT><DT><EM>True and false</EM><DD><PRE># C shell  True   - non-zero/non-empty value  False  - zero or null string# Bourne shell  True   - 0 returned by shell command  False  - non-zero returned by shell command  ( Note that "test" converts from C shell style to Bourne shell)# Perl  True   - non-zero/non-empty value  False  - zero or null string/* C */  True   - non zero integer  False  - zero integer</PRE><DT><EM>Input from tty</EM><DD><PRE># C shell   $&#60;# Bourne shell   line   read# Perl   &#60;STDIN&#62;/* C */   scanf</PRE><DT><EM>Redirection of I/O</EM><DD><PRE># C  shell  <VAR>command</VAR>  &#62;  file  <VAR>command</VAR>  &#62;&#38; file  <VAR>command</VAR>  &#62;&#62; file  <VAR>command1</VAR> |  <VAR>command2</VAR># Bourne shell  <VAR>command</VAR>  &#62; file  <VAR>command</VAR>  &#62; file 2&#62;&#38;1  <VAR>command</VAR>  &#62;&#62; file  <VAR>command1</VAR> | <VAR>command2</VAR># Perl  open (HANDLE,"&#62;file")  open (HANDLE,"&#62;file 2&#62;&#38;1")  open (HANDLE,"&#62;&#62;file")  open (HANDLE,"command1 |")  open (HANDLE,"| command2")/* C */  fopen ("file","w"); printf(..)  fopen ("file","w"); printf(..); fprintf(stderr,..)  fopen ("file","a"); printf(..)  popen ("<VAR>command1</VAR>","r")  popen ("<VAR>command2</VAR>","w")</PRE><DT><EM>Loops and tests</EM><DD><PRE>/* C */ Shell  foreach end         if then else endif  while end           switch case breaksw endsw  repeat# Bourne shell  while do done       if then else fi  until do done       case in esac  for in do done# Perl  while               if then else  for                 unless else  foreach  until  do while  do until/* C */  while               if then else  do while            switch case  for</PRE><DT><EM>Arguments from command line</EM><DD><PRE># C shell  $argv[]  $#argv# Bourne Shell  $1, $2, $3...  $*  $## Perl  $ARGV[]  $#ARGV/* C */  char argv[][]  int  argc</PRE><DT><EM>Arithmetic</EM><DD><PRE># C shell    a = $b + $c# Bourne shell   a = `expr $b + $c`# Perl   $a = $b + $c;/* C */   a = b + c;</PRE><DT><EM>Numerical comparison</EM><DD><PRE># C shell   if ( $x == $y ) then   endif# Bourne shell   if [ $x -eq $y ]; then   fi# Perl   if ( $x == $y )      {      }/* C */   if ( x == y )      {      }</PRE><DT><EM>String comparison</EM><DD><PRE># C shell   if ( $x == $y ) then   endif# Bourne shell   if [ $x = $y ]; then   fi# Perl   if ( $x eq $y ) then      {      }/* C */   if (strcmp(x,y) == 0)      {      }</PRE><DT><EM>Opening a file</EM><DD><PRE># C shell, Bourne shell - cannot be done (pipes only)# Perl    open (READ_HANDLE,"filename");    open (WRITE_HANDLE,"&#62; filename");    open (APPEND_HANDLE,"&#62;&#62; filename");/* C */    FILE *fp;    fp = fopen ("file","r");    fp = fopen ("file","w");    fp = fopen ("file","a");</PRE><DT><EM>Opening a directory</EM><DD><PRE># C shell   foreach dir ( <VAR>directory</VAR>/* )      ...   end# Bourne shell   for dir in <VAR>directory</VAR>/* ;   do     ...   done# Perl   opendir (HANDLE,"<VAR>directory</VAR>") || die;   while ($entry = readdir(HANDLE))      {      }   closedir(HANDLE);# C   #include &#60;dirent.h&#62;   DIR *dirh;   struct dirent *dirp;   if ((dirh = opendir(name)) == NULL)      {      perror("opendir")      exit(1);      }   for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh))      {      ...  /* dirp-&#62;d_name points to child */      }   closedir(dirh);   </PRE><DT><EM>Testing file types</EM><DD><PRE># C shell    if ( -f file )  # plain file    if ( -d file )  # directory# Bourne shell    if [ -f file ]  # plain file    if [ -d file ]  # directory# Perl    if ( -f file )  # plain file    if ( -d file )  # directory    if ( -l file )  # symbolic link/* C */     #include &#60;sys/stat.h&#62;     struct stat statvar;     stat("file", &#38;statvar);     if (S_ISREG(statvar.mode))  /* plain file */     if (S_ISDIR(statvar.mode))  /* directory  */     lstat("file", &#38;statvar);     if (S_ISLNK(statvar.mode))  /* symbolic link */</PRE></DL><H1><A NAME="SEC195" HREF="unix_toc.html#TOC195">Command and Variable Index</A></H1><P><H2>!</H2><DIR><LI><A HREF="unix.html#IDX554"><SAMP>`!'</SAMP> in Bash</A><LI><A HREF="unix.html#IDX697"><SAMP>`!'</SAMP> not</A><LI><A HREF="unix.html#IDX648"><SAMP>`!='</SAMP></A><LI><A HREF="unix.html#IDX547"><SAMP>`!='</SAMP> in Bash</A><LI><A HREF="unix.html#IDX654"><SAMP>`!~'</SAMP></A></DIR><H2>"</H2><DIR><LI><A HREF="unix.html#IDX505">"</A><LI><A HREF="unix.html#IDX156">" shell construction</A></DIR><H2>$</H2><DIR><LI><A HREF="unix.html#IDX144">$ in regular expressions</A><LI><A HREF="unix.html#IDX816">$&#60; in make</A><LI><A HREF="unix.html#IDX815">$? in make</A><LI><A HREF="unix.html#IDX814">$@ in make</A></DIR><H2>&#38;</H2><DIR><LI><A HREF="unix.html#IDX602">&#38;</A><LI><A HREF="unix.html#IDX693"><SAMP>`&#38;'</SAMP> AND</A></DIR><H2>'</H2><DIR><LI><A HREF="unix.html#IDX504">'</A></DIR><H2>(</H2><DIR><LI><A HREF="unix.html#IDX594">() in csh</A></DIR><H2>*</H2><DIR><LI><A HREF="unix.html#IDX134">*</A><LI><A HREF="unix.html#IDX146">* in regular expressions</A></DIR><H2>+</H2><DIR><LI><A HREF="unix.html#IDX682"><SAMP>`+'</SAMP></A><LI><A HREF="unix.html#IDX147">+ in regular expressions</A><LI><A HREF="unix.html#IDX684"><SAMP>`++'</SAMP></A><LI><A HREF="unix.html#IDX683"><SAMP>`+='</SAMP></A></DIR><H2>-</H2><DIR><LI><A HREF="unix.html#IDX685"><SAMP>`-'</SAMP></A><LI><A HREF="unix.html#IDX687"><SAMP>`--'</SAMP></A><LI><A HREF="unix.html#IDX23">--help</A><LI><A HREF="unix.html#IDX686"><SAMP>`-='</SAMP></A><LI><A HREF="unix.html#IDX555"><SAMP>`-a'</SAMP> in Bash</A><LI><A HREF="unix.html#IDX644">-d <VAR>file</VAR></A><LI><A HREF="unix.html#IDX539"><SAMP>`-d'</SAMP> in Bash</A><LI><A HREF="unix.html#IDX641">-e <VAR>file</VAR></A><LI><A HREF="unix.html#IDX548"><SAMP>`-eq'</SAMP> in Bash</A><LI><A HREF="unix.html#IDX643">-f <VAR>file</VAR></A><LI><A HREF="unix.html#IDX538"><SAMP>`-f'</SAMP> in Bash</A><LI><A HREF="unix.html#IDX544"><SAMP>`-g'</SAMP> in Bash</A><LI><A HREF="unix.html#IDX552"><SAMP>`-ge'</SAMP> in Bash</A><LI><A HREF="unix.html#IDX550"><SAMP>`-gt'</SAMP> in Bash</A><LI><A HREF="unix.html#IDX22">-h</A><LI><A HREF="unix.html#IDX553"><SAMP>`-le'</SAMP> in Bash</A><LI><A HREF="unix.html#IDX551"><SAMP>`-lt'</SAMP> in Bash</A><LI><A HREF="unix.html#IDX549"><SAMP>`-ne'</SAMP> in Bash</A><LI><A HREF="unix.html#IDX556"><SAMP>`-o'</SAMP> in Bash</A><LI><A HREF="unix.html#IDX639">-r <VAR>file</VAR></A><LI><A HREF="unix.html#IDX540"><SAMP>`-r'</SAMP> in Bash</A><LI><A HREF="unix.html#IDX543"><SAMP>`-s'</SAMP> in Bash</A><LI><A HREF="unix.html#IDX545"><SAMP>`-u'</SAMP> in Bash</A><LI><A HREF="unix.html#IDX640">-w <VAR>file</VAR></A><LI><A HREF="unix.html#IDX541"><SAMP>`-w'</SAMP> in Bash</A><LI><A HREF="unix.html#IDX542"><SAMP>`-x'</SAMP> in Bash</A><LI><A HREF="unix.html#IDX642">-z <VAR>file</VAR></A><LI><A HREF="unix.html#IDX776">-z in perl</A></DIR><H2>.</H2><DIR><LI><A HREF="unix.html#IDX64">.</A><LI><A HREF="unix.html#IDX142">. in regular expressions</A><LI><A HREF="unix.html#IDX65">..</A><LI><A HREF="unix.html#IDX488">..bashrc</A><LI><A HREF="unix.html#IDX487">.bash_profile</A><LI><A HREF="unix.html#IDX447">.xsession</A></DIR><H2>/</H2><DIR><LI><A HREF="unix.html#IDX74"><TT>`/bin'</TT></A><LI><A HREF="unix.html#IDX43"><TT>`/bin/csh'</TT></A><LI><A HREF="unix.html#IDX39"><TT>`/bin/sh'</TT></A><LI><A HREF="unix.html#IDX82"><TT>`/dev'</TT></A><LI><A HREF="unix.html#IDX83"><TT>`/devices'</TT></A><LI><A HREF="unix.html#IDX75"><TT>`/etc'</TT></A><LI><A HREF="unix.html#IDX81"><TT>`/export'</TT></A><LI><A HREF="unix.html#IDX84"><TT>`/home'</TT></A><LI><A HREF="unix.html#IDX79"><TT>`/sbin'</TT></A><LI><A HREF="unix.html#IDX80"><TT>`/sys'</TT></A><LI><A HREF="unix.html#IDX85"><TT>`/users'</TT></A><LI><A HREF="unix.html#IDX76"><TT>`/usr'</TT></A><LI><A HREF="unix.html#IDX77"><TT>`/usr/bin'</TT></A><LI><A HREF="unix.html#IDX78"><TT>`/usr/local'</TT></A><LI><A HREF="unix.html#IDX86"><TT>`/var'</TT></A><LI><A HREF="unix.html#IDX88"><TT>`/var/adm'</TT></A><LI><A HREF="unix.html#IDX87"><TT>`/vr/spool'</TT></A></DIR><H2>:</H2><DIR><LI><A HREF="unix.html#IDX678">:e</A><LI><A HREF="unix.html#IDX676">:h</A><LI><A HREF="unix.html#IDX679">:r</A><LI><A HREF="unix.html#IDX677">:t</A></DIR><H2>&#60;</H2><DIR><LI><A HREF="unix.html#IDX650"><SAMP>`&#60;'</SAMP></A><LI><A HREF="unix.html#IDX599">&#60;</A><LI><A HREF="unix.html#IDX690"><SAMP>`&#60;'</SAMP> less than</A><LI><A HREF="unix.html#IDX601">&#60;&#60;</A>, <A HREF="unix.html#IDX612">&#60;&#60;</A><LI><A HREF="unix.html#IDX696"><SAMP>`&#60;&#60;'</SAMP> shift</A><LI><A HREF="unix.html#IDX652"><SAMP>`&#60;='</SAMP></A></DIR><H2>=</H2><DIR><LI><A HREF="unix.html#IDX698"><SAMP>`='</SAMP> assignment</A><LI><A HREF="unix.html#IDX546"><SAMP>`='</SAMP> in Bash</A><LI><A HREF="unix.html#IDX647"><SAMP>`=='</SAMP></A>, <A HREF="unix.html#IDX720"><SAMP>`=='</SAMP></A><LI><A HREF="unix.html#IDX688"><SAMP>`=='</SAMP> equal to (compare)</A><LI><A HREF="unix.html#IDX653"><SAMP>`=~'</SAMP></A></DIR><H2>&#62;</H2><DIR><LI><A HREF="unix.html#IDX598">&#62;</A><LI><A HREF="unix.html#IDX649"><SAMP>`&#62;'</SAMP></A><LI><A HREF="unix.html#IDX689"><SAMP>`&#62;'</SAMP> greater than</A><LI><A HREF="unix.html#IDX651"><SAMP>`&#62;='</SAMP></A><LI><A HREF="unix.html#IDX600">&#62;&#62;</A><LI><A HREF="unix.html#IDX695"><SAMP>`&#62;&#62;'</SAMP> shift</A></DIR><H2>?</H2><DIR><LI><A HREF="unix.html#IDX133">?</A><LI><A HREF="unix.html#IDX148">? in regular expressions</A></DIR><H2>[</H2><DIR><LI><A HREF="unix.html#IDX135">[]</A><LI><A HREF="unix.html#IDX145">[] in regular expressions</A></DIR><H2>^</H2><DIR><LI><A HREF="unix.html#IDX143">^ in regular expressions</A><LI><A HREF="unix.html#IDX694"><SAMP>`^'</SAMP> XOR</A></DIR><H2>`</H2><DIR><LI><A HREF="unix.html#IDX506">`</A><LI><A HREF="unix.html#IDX157">`...`</A></DIR><H2>a</H2><DIR><LI><A HREF="unix.html#IDX18">apropos</A><LI><A HREF="unix.html#IDX343"><SAMP>`ar'</SAMP></A><LI><A HREF="unix.html#IDX383"><SAMP>`archie'</SAMP></A><LI><A HREF="unix.html#IDX822"><CODE>argc</CODE> in C</A><LI><A HREF="unix.html#IDX821"><CODE>argv</CODE> in C</A><LI><A HREF="unix.html#IDX282"><SAMP>`awk'</SAMP></A></DIR><H2>b</H2><DIR><LI><A HREF="unix.html#IDX673">breaksw</A></DIR><H2>c</H2><DIR><LI><A HREF="unix.html#IDX238"><SAMP>`cat'</SAMP></A><LI><A HREF="unix.html#IDX329"><SAMP>`cc'</SAMP></A><LI><A HREF="unix.html#IDX331"><SAMP>`CC'</SAMP></A><LI><A HREF="unix.html#IDX270"><SAMP>`chgrp'</SAMP></A><LI><A HREF="unix.html#IDX264"><SAMP>`chmod'</SAMP></A><LI><A HREF="unix.html#IDX268"><SAMP>`chown'</SAMP></A><LI><A HREF="unix.html#IDX189"><SAMP>`cmdtool'</SAMP></A><LI><A HREF="unix.html#IDX670">continue</A><LI><A HREF="unix.html#IDX215"><SAMP>`cp'</SAMP></A><LI><A HREF="unix.html#IDX766"><CODE>crypt()</CODE></A><LI><A HREF="unix.html#IDX162"><KBD>CTRL-A</KBD></A><LI><A HREF="unix.html#IDX164"><KBD>CTRL-C</KBD></A><LI><A HREF="unix.html#IDX166"><KBD>CTRL-D</KBD></A><LI><A HREF="unix.html#IDX168"><KBD>CTRL-E</KBD></A><LI><A HREF="unix.html#IDX170"><KBD>CTRL-L</KBD></A><LI><A HREF="unix.html#IDX172"><KBD>CTRL-Z</KBD></A><LI><A HREF="unix.html#IDX276"><SAMP>`cut'</SAMP></A></DIR><H2>d</H2><DIR><LI><A HREF="unix.html#IDX428"><SAMP>`date'</SAMP></A><LI><A HREF="unix.html#IDX346"><SAMP>`dbx'</SAMP></A><LI><A HREF="unix.html#IDX435"><SAMP>`dc'</SAMP></A><LI><A HREF="unix.html#IDX349">ddd</A><LI><A HREF="unix.html#IDX293"><SAMP>`df'</SAMP></A><LI><A HREF="unix.html#IDX120">DISPLAY</A><LI><A HREF="unix.html#IDX377"><SAMP>`domainname'</SAMP></A><LI><A HREF="unix.html#IDX291"><SAMP>`du'</SAMP></A><LI><A HREF="unix.html#IDX405"><SAMP>`dvips'</SAMP></A></DIR><H2>e</H2><DIR><LI><A HREF="unix.html#IDX199"><SAMP>`ed'</SAMP></A><LI><A HREF="unix.html#IDX315"><SAMP>`elm'</SAMP></A><LI><A HREF="unix.html#IDX203"><SAMP>`emacs'</SAMP></A><LI><A HREF="unix.html#IDX130">env</A><LI><A HREF="unix.html#IDX719"><SAMP>`eq'</SAMP></A></DIR><H2>f</H2><DIR><LI><A HREF="unix.html#IDX284"><SAMP>`find'</SAMP></A><LI><A HREF="unix.html#IDX297"><SAMP>`finger'</SAMP></A><LI><A HREF="unix.html#IDX274"><SAMP>`fmgr'</SAMP></A><LI><A HREF="unix.html#IDX391"><SAMP>`fnews'</SAMP></A><LI><A HREF="unix.html#IDX666">foreach</A><LI><A HREF="unix.html#IDX768"><CODE>fork()</CODE></A><LI><A HREF="unix.html#IDX324"><SAMP>`ftp'</SAMP></A></DIR><H2>g</H2><DIR><LI><A HREF="unix.html#IDX335"><SAMP>`g++'</SAMP></A><LI><A HREF="unix.html#IDX333"><SAMP>`gcc'</SAMP></A><LI><A HREF="unix.html#IDX348"><SAMP>`gdb'</SAMP></A><LI><A HREF="unix.html#IDX827"><CODE>getenv()</CODE></A><LI><A HREF="unix.html#IDX409"><SAMP>`ghostscript'</SAMP></A><LI><A HREF="unix.html#IDX407"><SAMP>`ghostview'</SAMP></A></DIR><H2>h</H2><DIR><LI><A HREF="unix.html#IDX124">HOME</A><LI><A HREF="unix.html#IDX122">HOSTNAME</A><LI><A HREF="unix.html#IDX375"><SAMP>`hostname'</SAMP></A></DIR><H2>i</H2><DIR><LI><A HREF="unix.html#IDX850">ioctl()</A><LI><A HREF="unix.html#IDX312"><SAMP>`irc'</SAMP></A><LI><A HREF="unix.html#IDX431"><SAMP>`ispell'</SAMP></A></DIR><H2>j</H2><DIR><LI><A HREF="unix.html#IDX339"><SAMP>`java'</SAMP></A><LI><A HREF="unix.html#IDX337"><SAMP>`javac'</SAMP></A></DIR><H2>k</H2><DIR><LI><A HREF="unix.html#IDX741">keys</A></DIR><H2>l</H2><DIR><LI><A HREF="unix.html#IDX399"><SAMP>`latex'</SAMP></A><LI><A HREF="unix.html#IDX341"><SAMP>`ld'</SAMP></A><LI><A HREF="unix.html#IDX798"><SAMP>`LD_LIBRARY_PATH'</SAMP></A><LI><A HREF="unix.html#IDX121">LD_LIBRARY_PATH</A><LI><A HREF="unix.html#IDX258"><SAMP>`less'</SAMP></A><LI><A HREF="unix.html#IDX99"><CODE>ln</CODE></A><LI><A HREF="unix.html#IDX96"><CODE>ln -s</CODE></A><LI><A HREF="unix.html#IDX286"><SAMP>`locate'</SAMP></A><LI><A HREF="unix.html#IDX242"><SAMP>`lp'</SAMP></A>, <A HREF="unix.html#IDX244"><SAMP>`lp'</SAMP></A><LI><A HREF="unix.html#IDX247"><SAMP>`lpq'</SAMP></A><LI><A HREF="unix.html#IDX251"><SAMP>`lpstat'</SAMP></A><LI><A HREF="unix.html#IDX213"><SAMP>`ls'</SAMP></A></DIR><H2>m</H2><DIR><LI><A HREF="unix.html#IDX19">man -k</A><LI><A HREF="unix.html#IDX307"><SAMP>`mesg'</SAMP></A><LI><A HREF="unix.html#IDX15">mkdir</A><LI><A HREF="unix.html#IDX231"><SAMP>`mkdir'</SAMP></A><LI><A HREF="unix.html#IDX253"><SAMP>`more'</SAMP></A><LI><A HREF="unix.html#IDX219"><SAMP>`mv'</SAMP></A></DIR><H2>n</H2><DIR><LI><A HREF="unix.html#IDX326"><SAMP>`ncftp'</SAMP></A><LI><A HREF="unix.html#IDX364"><SAMP>`netstat'</SAMP></A><LI><A HREF="unix.html#IDX380"><SAMP>`nslookup'</SAMP></A></DIR><H2>p</H2><DIR><LI><A HREF="unix.html#IDX278"><SAMP>`paste'</SAMP></A><LI><A HREF="unix.html#IDX118">PATH</A><LI><A HREF="unix.html#IDX356"><SAMP>`php'</SAMP></A><LI><A HREF="unix.html#IDX207"><SAMP>`pico'</SAMP></A><LI><A HREF="unix.html#IDX317"><SAMP>`pine'</SAMP></A><LI><A HREF="unix.html#IDX437"><SAMP>`ping'</SAMP></A><LI><A HREF="unix.html#IDX123">PRINTER</A><LI><A HREF="unix.html#IDX240"><SAMP>`PRINTER'</SAMP></A><LI><A HREF="unix.html#IDX360"><SAMP>`ps'</SAMP></A></DIR><H2>r</H2><DIR><LI><A HREF="unix.html#IDX767"><CODE>rand()</CODE></A><LI><A HREF="unix.html#IDX366"><SAMP>`rcpinfo'</SAMP></A><LI><A HREF="unix.html#IDX777"><SAMP>`rename'</SAMP> in perl</A><LI><A HREF="unix.html#IDX667">repeat</A><LI><A HREF="unix.html#IDX193"><SAMP>`rlogin'</SAMP></A><LI><A HREF="unix.html#IDX319"><SAMP>`rmail'</SAMP></A><LI><A HREF="unix.html#IDX236"><SAMP>`rmdir'</SAMP></A><LI><A HREF="unix.html#IDX195"><SAMP>`rsh'</SAMP></A></DIR><H2>s</H2><DIR><LI><A HREF="unix.html#IDX191"><SAMP>`screen'</SAMP></A><LI><A HREF="unix.html#IDX280"><SAMP>`sed'</SAMP></A><LI><A HREF="unix.html#IDX588">set</A><LI><A HREF="unix.html#IDX426"><SAMP>`setroot'</SAMP></A><LI><A HREF="unix.html#IDX187"><SAMP>`shelltool'</SAMP></A><LI><A HREF="unix.html#IDX369"><SAMP>`showmount'</SAMP></A><LI><A HREF="unix.html#IDX63">stderr</A><LI><A HREF="unix.html#IDX61">stdin</A><LI><A HREF="unix.html#IDX62">stdout</A></DIR><H2>t</H2><DIR><LI><A HREF="unix.html#IDX309"><SAMP>`talk'</SAMP></A><LI><A HREF="unix.html#IDX354"><SAMP>`tcl'</SAMP></A><LI><A HREF="unix.html#IDX197"><SAMP>`telnet'</SAMP></A><LI><A HREF="unix.html#IDX119">TERM</A><LI><A HREF="unix.html#IDX397"><SAMP>`tex'</SAMP></A><LI><A HREF="unix.html#IDX402"><SAMP>`texinfo'</SAMP></A><LI><A HREF="unix.html#IDX211"><SAMP>`textedit'</SAMP></A><LI><A HREF="unix.html#IDX221"><SAMP>`touch'</SAMP></A></DIR><H2>u</H2><DIR><LI><A HREF="unix.html#IDX371"><SAMP>`uname'</SAMP></A><LI><A HREF="unix.html#IDX227"><SAMP>`unlink'</SAMP></A>, <A HREF="unix.html#IDX229"><SAMP>`unlink'</SAMP></A><LI><A HREF="unix.html#IDX589">unset</A><LI><A HREF="unix.html#IDX295"><SAMP>`users'</SAMP></A></DIR><H2>v</H2><DIR><LI><A HREF="unix.html#IDX201"><SAMP>`vi'</SAMP></A><LI><A HREF="unix.html#IDX362"><SAMP>`vmstat'</SAMP></A><LI><A HREF="unix.html#IDX89"><TT>`vmunix'</TT></A></DIR><H2>w</H2><DIR><LI><A HREF="unix.html#IDX301"><SAMP>`w'</SAMP></A><LI><A HREF="unix.html#IDX288"><SAMP>`whereis'</SAMP></A><LI><A HREF="unix.html#IDX116">which</A><LI><A HREF="unix.html#IDX668">while</A><LI><A HREF="unix.html#IDX299"><SAMP>`who'</SAMP></A><LI><A HREF="unix.html#IDX305"><SAMP>`write'</SAMP></A></DIR><H2>x</H2><DIR><LI><A HREF="unix.html#IDX387"><SAMP>`xarchie'</SAMP></A><LI><A HREF="unix.html#IDX433"><SAMP>`xcalc'</SAMP></A><LI><A HREF="unix.html#IDX403"><SAMP>`xdvi'</SAMP></A><LI><A HREF="unix.html#IDX209"><SAMP>`xedit'</SAMP></A><LI><A HREF="unix.html#IDX205"><SAMP>`xemacs'</SAMP></A><LI><A HREF="unix.html#IDX420"><SAMP>`xfig'</SAMP></A><LI><A HREF="unix.html#IDX393"><SAMP>`xmosaic'</SAMP></A><LI><A HREF="unix.html#IDX417"><SAMP>`xpaint'</SAMP></A>, <A HREF="unix.html#IDX423"><SAMP>`xpaint'</SAMP></A><LI><A HREF="unix.html#IDX389"><SAMP>`xrn'</SAMP></A><LI><A HREF="unix.html#IDX185"><SAMP>`xterm'</SAMP></A><LI><A HREF="unix.html#IDX412"><SAMP>`xv'</SAMP></A><LI><A HREF="unix.html#IDX352"><SAMP>`xxgdb'</SAMP></A></DIR><H2>z</H2><DIR><LI><A HREF="unix.html#IDX321"><SAMP>`zmail'</SAMP></A></DIR><H2>|</H2><DIR><LI><A HREF="unix.html#IDX597">|</A><LI><A HREF="unix.html#IDX692"><SAMP>`|'</SAMP> OR</A><LI><A HREF="unix.html#IDX691"><SAMP>`||'</SAMP> logical OR</A></DIR></P><H1><A NAME="SEC196" HREF="unix_toc.html#TOC196">Concept Index</A></H1><P><H2>#</H2><DIR><LI><A HREF="unix.html#IDX530"><SAMP>`#!program'</SAMP> sequence</A>, <A HREF="unix.html#IDX624"><SAMP>`#!program'</SAMP> sequence</A></DIR><H2>$</H2><DIR><LI><A HREF="unix.html#IDX151">$ in regular expressions</A><LI><A HREF="unix.html#IDX672"><SAMP>`$&#60;'</SAMP> operator</A></DIR><H2>'</H2><DIR><LI><A HREF="unix.html#IDX503"><KBD>'</KBD> and <KBD>"</KBD></A></DIR><H2>(</H2><DIR><LI><A HREF="unix.html#IDX632">() and subshells</A><LI><A HREF="unix.html#IDX593">() operators to make array in csh</A></DIR><H2>*</H2><DIR><LI><A HREF="unix.html#IDX153">* in regular expressions</A></DIR><H2>+</H2><DIR><LI><A HREF="unix.html#IDX154">+ in regular expressions</A></DIR><H2>-</H2><DIR><LI><A HREF="unix.html#IDX805"><SAMP>`-I'</SAMP> option to <CODE>cc</CODE></A><LI><A HREF="unix.html#IDX803"><SAMP>`-L'</SAMP> option to <CODE>cc</CODE></A></DIR><H2>.</H2><DIR><LI><A HREF="unix.html#IDX66">. directory</A>, <A HREF="unix.html#IDX91">. directory</A><LI><A HREF="unix.html#IDX149">. in regular expressions</A><LI><A HREF="unix.html#IDX67">.. directory</A>, <A HREF="unix.html#IDX92">.. directory</A><LI><A HREF="unix.html#IDX489"><TT>`.bash_profile'</TT> set up in Bash</A><LI><A HREF="unix.html#IDX577"><TT>`.cshrc'</TT> file</A><LI><A HREF="unix.html#IDX578"><TT>`.login'</TT> file</A><LI><A HREF="unix.html#IDX448">.xsession file</A></DIR><H2>/</H2><DIR><LI><A HREF="unix.html#IDX464"><TT>`/etc/group'</TT></A></DIR><H2>&#60;</H2><DIR><LI><A HREF="unix.html#IDX749"><SAMP>`&#60;&#62;'</SAMP> filehandle in perl</A></DIR><H2>?</H2><DIR><LI><A HREF="unix.html#IDX155">? in regular expressions</A></DIR><H2>[</H2><DIR><LI><A HREF="unix.html#IDX558"><SAMP>`[]'</SAMP> for test in Bash</A><LI><A HREF="unix.html#IDX152">[] in regular expressions</A></DIR><H2>^</H2><DIR><LI><A HREF="unix.html#IDX150">^ in regular expressions</A></DIR><H2>`</H2><DIR><LI><A HREF="unix.html#IDX508"><KBD>`</KBD> symbol and embedded shells</A><LI><A HREF="unix.html#IDX713"><SAMP>``..`'</SAMP> in perl</A></DIR><H2>a</H2><DIR><LI><A HREF="unix.html#IDX797"><TT>`a.out'</TT></A><LI><A HREF="unix.html#IDX868"><CODE>accept()</CODE></A><LI><A HREF="unix.html#IDX467">Access bits</A><LI><A HREF="unix.html#IDX472">Access bits, octal form</A><LI><A HREF="unix.html#IDX471">Access bits, text form</A><LI><A HREF="unix.html#IDX261">Access control</A><LI><A HREF="unix.html#IDX271">Access control lists</A><LI><A HREF="unix.html#IDX461">Access rights</A><LI><A HREF="unix.html#IDX459">Access to files</A><LI><A HREF="unix.html#IDX272">ACLs</A><LI><A HREF="unix.html#IDX790">ANSI C</A><LI><A HREF="unix.html#IDX609">Appending to a file with <SAMP>`&#62;&#62;'</SAMP></A><LI><A HREF="unix.html#IDX17">apropos</A><LI><A HREF="unix.html#IDX342"><SAMP>`ar'</SAMP> archiver</A><LI><A HREF="unix.html#IDX382"><SAMP>`archie'</SAMP> program</A><LI><A HREF="unix.html#IDX626">Argument vector in csh</A><LI><A HREF="unix.html#IDX710">Argument vector in perl</A>, <A HREF="unix.html#IDX722">Argument vector in perl</A><LI><A HREF="unix.html#IDX628">Arguments, command line</A><LI><A HREF="unix.html#IDX627"><SAMP>`argv'</SAMP></A><LI><A HREF="unix.html#IDX527">Arithmetic in Bash</A><LI><A HREF="unix.html#IDX681">Arithmetic operations in csh</A><LI><A HREF="unix.html#IDX729">Arrays (associated) in perl</A><LI><A HREF="unix.html#IDX721">Arrays (normal) in perl</A><LI><A HREF="unix.html#IDX728">Arrays and <SAMP>`split'</SAMP></A><LI><A HREF="unix.html#IDX592">Arrays in csh</A><LI><A HREF="unix.html#IDX709">Arrays in perl</A><LI><A HREF="unix.html#IDX742">Associated arrays, iteration</A><LI><A HREF="unix.html#IDX576"><SAMP>`at'</SAMP> command</A><LI><A HREF="unix.html#IDX10">AT&#38;T</A><LI><A HREF="unix.html#IDX281"><SAMP>`awk'</SAMP></A><LI><A HREF="unix.html#IDX704"><SAMP>`awk'</SAMP> pattern extractor</A></DIR><H2>b</H2><DIR><LI><A HREF="unix.html#IDX425"><SAMP>`Background picture'</SAMP></A><LI><A HREF="unix.html#IDX512">Background process</A>, <A HREF="unix.html#IDX515">Background process</A><LI><A HREF="unix.html#IDX507">Backwards quotes</A><LI><A HREF="unix.html#IDX45">bash</A>, <A HREF="unix.html#IDX174">bash</A><LI><A HREF="unix.html#IDX575"><SAMP>`batch'</SAMP> command</A><LI><A HREF="unix.html#IDX884">Berkeley Internet Name Domain (BIND)</A><LI><A HREF="unix.html#IDX518"><SAMP>`bg'</SAMP> command</A><LI><A HREF="unix.html#IDX859">Big endian</A><LI><A HREF="unix.html#IDX883">BIND</A><LI><A HREF="unix.html#IDX866"><CODE>bind()</CODE></A><LI><A HREF="unix.html#IDX486">Bourne Again shell</A><LI><A HREF="unix.html#IDX38">Bourne shell</A><LI><A HREF="unix.html#IDX525">Break key</A><LI><A HREF="unix.html#IDX674"><SAMP>`breaksw'</SAMP></A><LI><A HREF="unix.html#IDX255">Browsing through a file</A><LI><A HREF="unix.html#IDX11">BSD</A><LI><A HREF="unix.html#IDX660">Build software script</A><LI><A HREF="unix.html#IDX31">Built in commands</A><LI><A HREF="unix.html#IDX857">Byte order</A></DIR><H2>c</H2><DIR><LI><A HREF="unix.html#IDX6">C</A><LI><A HREF="unix.html#IDX50">C library calls and shell commands</A><LI><A HREF="unix.html#IDX783">C programming</A><LI><A HREF="unix.html#IDX41">C shell</A><LI><A HREF="unix.html#IDX580">C shell setup files</A><LI><A HREF="unix.html#IDX817">C++ suffix rules</A><LI><A HREF="unix.html#IDX48">C, role in unix</A><LI><A HREF="unix.html#IDX434">Calculator, shell</A><LI><A HREF="unix.html#IDX432">Calculator, X windows</A><LI><A HREF="unix.html#IDX237"><SAMP>`cat'</SAMP> command</A><LI><A HREF="unix.html#IDX330"><SAMP>`CC'</SAMP></A><LI><A HREF="unix.html#IDX328"><SAMP>`cc'</SAMP></A><LI><A HREF="unix.html#IDX779">CGI protocol</A><LI><A HREF="unix.html#IDX265">Changing file mode</A><LI><A HREF="unix.html#IDX482"><CODE>chgrp</CODE> command</A><LI><A HREF="unix.html#IDX269"><SAMP>`chgrp'</SAMP> command</A><LI><A HREF="unix.html#IDX473"><CODE>chmod</CODE> command</A><LI><A HREF="unix.html#IDX263"><SAMP>`chmod'</SAMP> command</A><LI><A HREF="unix.html#IDX755"><SAMP>`chop'</SAMP> command in perl</A><LI><A HREF="unix.html#IDX267"><SAMP>`chown'</SAMP> command</A><LI><A HREF="unix.html#IDX481"><CODE>chown</CODE> command</A><LI><A HREF="unix.html#IDX748"><SAMP>`close'</SAMP> command in perl</A><LI><A HREF="unix.html#IDX829"><CODE>closedir</CODE> command</A><LI><A HREF="unix.html#IDX188"><SAMP>`cmdtool'</SAMP></A><LI><A HREF="unix.html#IDX500">Command completion</A><LI><A HREF="unix.html#IDX497">Command history</A><LI><A HREF="unix.html#IDX109">Command interpreter</A><LI><A HREF="unix.html#IDX625">Command line arguments</A><LI><A HREF="unix.html#IDX531">Command line arguments in Bash</A><LI><A HREF="unix.html#IDX820">Command line arguments in C</A><LI><A HREF="unix.html#IDX711">Command line arguments in perl</A>, <A HREF="unix.html#IDX723">Command line arguments in perl</A><LI><A HREF="unix.html#IDX114">Command path</A><LI><A HREF="unix.html#IDX183">Command window</A><LI><A HREF="unix.html#IDX30">Commands as files</A><LI><A HREF="unix.html#IDX33">Commands path</A><LI><A HREF="unix.html#IDX645">Comparison operators in csh</A><LI><A HREF="unix.html#IDX661">Compiler script</A><LI><A HREF="unix.html#IDX327">Compilers</A><LI><A HREF="unix.html#IDX811">Compiling huge programs</A><LI><A HREF="unix.html#IDX795">Compiling programs</A><LI><A HREF="unix.html#IDX863"><CODE>connect()</CODE></A><LI><A HREF="unix.html#IDX669"><SAMP>`continue'</SAMP> in csh</A><LI><A HREF="unix.html#IDX633">Continuing long lines</A><LI><A HREF="unix.html#IDX619">Copy of output to file</A><LI><A HREF="unix.html#IDX27">core</A><LI><A HREF="unix.html#IDX214"><SAMP>`cp'</SAMP> command</A><LI><A HREF="unix.html#IDX232">Creating directories</A><LI><A HREF="unix.html#IDX222">Creating files</A><LI><A HREF="unix.html#IDX175">csh</A><LI><A HREF="unix.html#IDX42"><TT>`csh'</TT></A><LI><A HREF="unix.html#IDX161"><KBD>CTRL-A</KBD></A><LI><A HREF="unix.html#IDX163"><KBD>CTRL-C</KBD></A><LI><A HREF="unix.html#IDX165"><KBD>CTRL-D</KBD></A><LI><A HREF="unix.html#IDX567"><KBD>CTRL-D</KBD> and EOF</A><LI><A HREF="unix.html#IDX167"><KBD>CTRL-E</KBD></A><LI><A HREF="unix.html#IDX169"><KBD>CTRL-L</KBD></A><LI><A HREF="unix.html#IDX171"><KBD>CTRL-Z</KBD></A><LI><A HREF="unix.html#IDX785">Curses</A><LI><A HREF="unix.html#IDX705"><SAMP>`cut'</SAMP></A><LI><A HREF="unix.html#IDX751">Cut as a perl script</A><LI><A HREF="unix.html#IDX275"><SAMP>`cut'</SAMP> command</A></DIR><H2>d</H2><DIR><LI><A HREF="unix.html#IDX873">Database maps</A><LI><A HREF="unix.html#IDX770">Database support</A><LI><A HREF="unix.html#IDX427"><SAMP>`date'</SAMP> command</A><LI><A HREF="unix.html#IDX224">Date stamp, updating</A><LI><A HREF="unix.html#IDX344"><SAMP>`dbx'</SAMP> debugger</A><LI><A HREF="unix.html#IDX345">Debugger</A><LI><A HREF="unix.html#IDX52">Debugger for C</A><LI><A HREF="unix.html#IDX351">Debugger GUI</A><LI><A HREF="unix.html#IDX536">Decisions and return codes in Bash</A><LI><A HREF="unix.html#IDX26">delete</A><LI><A HREF="unix.html#IDX813">Dependencies in Makefiles</A><LI><A HREF="unix.html#IDX292"><SAMP>`df'</SAMP> command</A><LI><A HREF="unix.html#IDX760"><SAMP>`die'</SAMP></A><LI><A HREF="unix.html#IDX233">Directories, creating</A><LI><A HREF="unix.html#IDX234">Directories, deleting</A><LI><A HREF="unix.html#IDX831">dirent directory interface</A><LI><A HREF="unix.html#IDX289">Disk usage.</A><LI><A HREF="unix.html#IDX450">DISPLAY variable</A><LI><A HREF="unix.html#IDX446">Display, X</A><LI><A HREF="unix.html#IDX881">DNS</A><LI><A HREF="unix.html#IDX737"><SAMP>`do..while'</SAMP> in perl</A><LI><A HREF="unix.html#IDX378">Domainname</A><LI><A HREF="unix.html#IDX376"><SAMP>`domainname'</SAMP> command</A><LI><A HREF="unix.html#IDX421">Drawing program</A><LI><A HREF="unix.html#IDX290"><SAMP>`du'</SAMP> command</A><LI><A HREF="unix.html#IDX404">dvi to postscript</A></DIR><H2>e</H2><DIR><LI><A HREF="unix.html#IDX198"><SAMP>`ed'</SAMP></A><LI><A HREF="unix.html#IDX141"><CODE>egrep</CODE> command</A><LI><A HREF="unix.html#IDX314"><SAMP>`elm'</SAMP> mailer</A><LI><A HREF="unix.html#IDX202"><SAMP>`emacs'</SAMP></A><LI><A HREF="unix.html#IDX509">Embedded shell</A><LI><A HREF="unix.html#IDX763">Encryption</A><LI><A HREF="unix.html#IDX568">End of file <KBD>CTRL-D</KBD></A><LI><A HREF="unix.html#IDX129"><CODE>env</CODE> command</A><LI><A HREF="unix.html#IDX111">Environment variables</A>, <A HREF="unix.html#IDX117">Environment variables</A><LI><A HREF="unix.html#IDX824">Environment variables in C</A>, <A HREF="unix.html#IDX825">Environment variables in C</A><LI><A HREF="unix.html#IDX712">Environment variables in perl</A>, <A HREF="unix.html#IDX730">Environment variables in perl</A><LI><A HREF="unix.html#IDX105">Environment, UNIX user</A><LI><A HREF="unix.html#IDX823"><CODE>envp</CODE> in C</A><LI><A HREF="unix.html#IDX718"><SAMP>`eq'</SAMP> and <SAMP>`=='</SAMP> in perl</A><LI><A HREF="unix.html#IDX68">Error messages</A><LI><A HREF="unix.html#IDX761">Errors in perl</A><LI><A HREF="unix.html#IDX480">Executable, making programs</A><LI><A HREF="unix.html#IDX759">Exiting on errors in perl</A><LI><A HREF="unix.html#IDX494"><SAMP>`EXPORT'</SAMP> command in Bash</A><LI><A HREF="unix.html#IDX140">Expressions, regular</A><LI><A HREF="unix.html#IDX793"><CODE>extern</CODE> variables</A><LI><A HREF="unix.html#IDX680">Extracting filename components</A></DIR><H2>f</H2><DIR><LI><A HREF="unix.html#IDX517"><SAMP>`fg'</SAMP> command |</A><LI><A HREF="unix.html#IDX462">File access permission</A><LI><A HREF="unix.html#IDX750">File handles in perl</A><LI><A HREF="unix.html#IDX72">File hierarchy</A><LI><A HREF="unix.html#IDX266">File mode, changing</A><LI><A HREF="unix.html#IDX465">File protection bits</A><LI><A HREF="unix.html#IDX322">File transfer</A><LI><A HREF="unix.html#IDX841">File type, determining in C</A><LI><A HREF="unix.html#IDX499">Filename completion</A><LI><A HREF="unix.html#IDX745">Files in perl</A><LI><A HREF="unix.html#IDX744">Files, iterating over lines</A><LI><A HREF="unix.html#IDX283"><SAMP>`find'</SAMP> command</A>, <A HREF="unix.html#IDX513"><SAMP>`find'</SAMP> command</A><LI><A HREF="unix.html#IDX20">Finding commands</A><LI><A HREF="unix.html#IDX385">Finding FTP files</A><LI><A HREF="unix.html#IDX296"><SAMP>`finger'</SAMP> service</A><LI><A HREF="unix.html#IDX273"><SAMP>`fmgr'</SAMP> file manager</A><LI><A HREF="unix.html#IDX390"><SAMP>`fnews'</SAMP> news reader</A><LI><A HREF="unix.html#IDX738">For loop</A><LI><A HREF="unix.html#IDX532"><CODE>for</CODE> loop in Bash</A><LI><A HREF="unix.html#IDX732"><CODE>for</CODE> loop in perl</A><LI><A HREF="unix.html#IDX731">For loops in perl</A><LI><A HREF="unix.html#IDX663"><CODE>foreach</CODE></A><LI><A HREF="unix.html#IDX629"><CODE>foreach</CODE> example</A><LI><A HREF="unix.html#IDX739">Foreach loop</A><LI><A HREF="unix.html#IDX733"><CODE>foreach</CODE> loop in perl</A><LI><A HREF="unix.html#IDX511">Foreground process</A><LI><A HREF="unix.html#IDX769">Forking new processes</A><LI><A HREF="unix.html#IDX610">Formatting text in a file</A><LI><A HREF="unix.html#IDX781">Forms in HTML</A><LI><A HREF="unix.html#IDX323"><SAMP>`ftp'</SAMP> program</A><LI><A HREF="unix.html#IDX384">FTP resources, finding</A><LI><A HREF="unix.html#IDX885">Fully qualified name</A></DIR><H2>g</H2><DIR><LI><A HREF="unix.html#IDX334"><SAMP>`g++'</SAMP></A><LI><A HREF="unix.html#IDX332"><SAMP>`gcc'</SAMP></A><LI><A HREF="unix.html#IDX347"><SAMP>`gdb'</SAMP> debugger</A><LI><A HREF="unix.html#IDX826"><CODE>getenv() function</CODE></A><LI><A HREF="unix.html#IDX876"><CODE>getgrnam()</CODE></A><LI><A HREF="unix.html#IDX861"><CODE>gethostbyname()</CODE></A>, <A HREF="unix.html#IDX886"><CODE>gethostbyname()</CODE></A><LI><A HREF="unix.html#IDX877"><CODE>gethostent()</CODE></A><LI><A HREF="unix.html#IDX878"><CODE>getnetgrent()</CODE></A><LI><A HREF="unix.html#IDX874"><CODE>getpwnam()</CODE></A><LI><A HREF="unix.html#IDX875"><CODE>getpwuid()</CODE></A><LI><A HREF="unix.html#IDX879"><CODE>getservbyname()</CODE></A><LI><A HREF="unix.html#IDX880"><CODE>getservbyport()</CODE></A><LI><A HREF="unix.html#IDX160">Getting command output into a string</A><LI><A HREF="unix.html#IDX408"><SAMP>`ghostscript'</SAMP> "GNU postscript" interpreter</A><LI><A HREF="unix.html#IDX406"><SAMP>`ghostview'</SAMP> postscript previewer</A><LI><A HREF="unix.html#IDX413">gif</A><LI><A HREF="unix.html#IDX125">Global variables</A><LI><A HREF="unix.html#IDX492">Global variables in Bash</A><LI><A HREF="unix.html#IDX587">Global variables in csh</A><LI><A HREF="unix.html#IDX262">Granting permission</A><LI><A HREF="unix.html#IDX424">Graphing program</A><LI><A HREF="unix.html#IDX463">groups</A></DIR><H2>h</H2><DIR><LI><A HREF="unix.html#IDX93">Hard links</A>, <A HREF="unix.html#IDX98">Hard links</A><LI><A HREF="unix.html#IDX21">Help function for commands</A><LI><A HREF="unix.html#IDX73">Hierarchy, file</A><LI><A HREF="unix.html#IDX374"><SAMP>`hostname'</SAMP> command</A><LI><A HREF="unix.html#IDX400">Hypertext</A></DIR><H2>i</H2><DIR><LI><A HREF="unix.html#IDX57">I/O streams</A><LI><A HREF="unix.html#IDX734"><SAMP>`if'</SAMP> in perl</A><LI><A HREF="unix.html#IDX636"><CODE>if..then..else</CODE> in csh</A><LI><A HREF="unix.html#IDX559"><CODE>if..then..else..fi</CODE> in Bash</A><LI><A HREF="unix.html#IDX564"><SAMP>`IFS'</SAMP> variable in Bash</A><LI><A HREF="unix.html#IDX856"><CODE>INADDR_ANY</CODE></A><LI><A HREF="unix.html#IDX806">Include file search path</A><LI><A HREF="unix.html#IDX804">Include files</A><LI><A HREF="unix.html#IDX101">Index nodes</A><LI><A HREF="unix.html#IDX832">Information about file properties</A><LI><A HREF="unix.html#IDX110"><EM>init</EM></A><LI><A HREF="unix.html#IDX100">inodes</A><LI><A HREF="unix.html#IDX560">Input in Bash</A><LI><A HREF="unix.html#IDX671">Input in csh</A><LI><A HREF="unix.html#IDX613">Input over many lines</A><LI><A HREF="unix.html#IDX158">Inserting a command into a string</A><LI><A HREF="unix.html#IDX311">Internet relay chat</A><LI><A HREF="unix.html#IDX381">Internet resources</A><LI><A HREF="unix.html#IDX717">Interpretation of values in perl</A><LI><A HREF="unix.html#IDX571">Interrupt handler in Bash</A><LI><A HREF="unix.html#IDX849"><CODE>ioctl()</CODE></A><LI><A HREF="unix.html#IDX310"><SAMP>`IRC'</SAMP></A><LI><A HREF="unix.html#IDX743">Iterating over files</A><LI><A HREF="unix.html#IDX740">Iteration over arrays</A></DIR><H2>j</H2><DIR><LI><A HREF="unix.html#IDX338"><SAMP>`java'</SAMP></A><LI><A HREF="unix.html#IDX336"><SAMP>`javac'</SAMP></A><LI><A HREF="unix.html#IDX510">Job control</A><LI><A HREF="unix.html#IDX519">Job numbers in csh</A><LI><A HREF="unix.html#IDX523">Job, moving to background</A><LI><A HREF="unix.html#IDX132">Joker notation</A><LI><A HREF="unix.html#IDX414">jpg</A><LI><A HREF="unix.html#IDX176">jsh</A></DIR><H2>k</H2><DIR><LI><A HREF="unix.html#IDX90">Kernel</A><LI><A HREF="unix.html#IDX36">kernel</A><LI><A HREF="unix.html#IDX791">Kernighan and Ritchie C</A><LI><A HREF="unix.html#IDX520"><SAMP>`kill'</SAMP> command</A><LI><A HREF="unix.html#IDX46">ksh</A>, <A HREF="unix.html#IDX177">ksh</A></DIR><H2>l</H2><DIR><LI><A HREF="unix.html#IDX398"><SAMP>`latex'</SAMP></A><LI><A HREF="unix.html#IDX340"><SAMP>`ld'</SAMP> loader/linker</A><LI><A HREF="unix.html#IDX809"><TT>`ld.so.cache'</TT></A><LI><A HREF="unix.html#IDX810"><TT>`ldconfig'</TT></A><LI><A HREF="unix.html#IDX257"><SAMP>`less'</SAMP> command</A><LI><A HREF="unix.html#IDX54">lex</A><LI><A HREF="unix.html#IDX788"><SAMP>`lex'</SAMP></A><LI><A HREF="unix.html#IDX851">Lexer</A><LI><A HREF="unix.html#IDX799">libc</A><LI><A HREF="unix.html#IDX801">libcurses</A><LI><A HREF="unix.html#IDX800">libm</A><LI><A HREF="unix.html#IDX802">Library path for C loader</A><LI><A HREF="unix.html#IDX701">Limitations of shell programs</A><LI><A HREF="unix.html#IDX838">Links in C</A><LI><A HREF="unix.html#IDX837">Links, where do they point?</A><LI><A HREF="unix.html#IDX867"><CODE>listen()</CODE></A><LI><A HREF="unix.html#IDX860">Little endian</A><LI><A HREF="unix.html#IDX97"><CODE>ln -s</CODE></A><LI><A HREF="unix.html#IDX127">Local variables</A><LI><A HREF="unix.html#IDX493">Local variables in Bash</A><LI><A HREF="unix.html#IDX585">Local variables in csh</A><LI><A HREF="unix.html#IDX757">Local variables in perl</A><LI><A HREF="unix.html#IDX285"><SAMP>`locate'</SAMP> command</A><LI><A HREF="unix.html#IDX103">Logging on</A><LI><A HREF="unix.html#IDX107">Login environment</A>, <A HREF="unix.html#IDX579">Login environment</A><LI><A HREF="unix.html#IDX468">Long file listing</A><LI><A HREF="unix.html#IDX634">Long lines, continuing</A><LI><A HREF="unix.html#IDX566">Loops and list separators</A><LI><A HREF="unix.html#IDX561">Loops in Bash</A><LI><A HREF="unix.html#IDX662">Loops in csh</A><LI><A HREF="unix.html#IDX241"><SAMP>`lp'</SAMP> command</A><LI><A HREF="unix.html#IDX246"><SAMP>`lpq'</SAMP></A><LI><A HREF="unix.html#IDX243"><SAMP>`lpr'</SAMP> command</A><LI><A HREF="unix.html#IDX250"><SAMP>`lpstat'</SAMP></A><LI><A HREF="unix.html#IDX469"><CODE>ls -l</CODE></A><LI><A HREF="unix.html#IDX212"><SAMP>`ls command'</SAMP></A><LI><A HREF="unix.html#IDX835"><CODE>lstat()</CODE></A></DIR><H2>m</H2><DIR><LI><A HREF="unix.html#IDX8">MacIntosh</A><LI><A HREF="unix.html#IDX839">Macros for stat</A><LI><A HREF="unix.html#IDX313">Mail clients</A><LI><A HREF="unix.html#IDX53">make</A><LI><A HREF="unix.html#IDX818">Make rules for C++</A><LI><A HREF="unix.html#IDX659">Make software script</A><LI><A HREF="unix.html#IDX622">Making a script</A><LI><A HREF="unix.html#IDX14">Making directories</A><LI><A HREF="unix.html#IDX529">Making scripts in Bash</A><LI><A HREF="unix.html#IDX479">Masking programs executable</A><LI><A HREF="unix.html#IDX136">Matching filenames</A>, <A HREF="unix.html#IDX137">Matching filenames</A><LI><A HREF="unix.html#IDX138">Matching strings</A><LI><A HREF="unix.html#IDX260">mc</A><LI><A HREF="unix.html#IDX358">Mercury</A><LI><A HREF="unix.html#IDX306"><SAMP>`mesg'</SAMP></A><LI><A HREF="unix.html#IDX303">Messages</A><LI><A HREF="unix.html#IDX780">Mime types in W3</A><LI><A HREF="unix.html#IDX16">mkdir</A><LI><A HREF="unix.html#IDX230"><SAMP>`mkdir'</SAMP> command</A><LI><A HREF="unix.html#IDX252"><SAMP>`more'</SAMP> command</A><LI><A HREF="unix.html#IDX392"><SAMP>`mosaic'</SAMP></A><LI><A HREF="unix.html#IDX368">Mounted file systems</A><LI><A HREF="unix.html#IDX522">Moving a job to the background</A><LI><A HREF="unix.html#IDX218">Moving files</A><LI><A HREF="unix.html#IDX796">Multiple C files, compiling</A><LI><A HREF="unix.html#IDX458">Multiple screens</A><LI><A HREF="unix.html#IDX216"><SAMP>`mv'</SAMP> command</A></DIR><H2>n</H2><DIR><LI><A HREF="unix.html#IDX259">nc</A><LI><A HREF="unix.html#IDX325"><SAMP>`ncftp'</SAMP> program</A><LI><A HREF="unix.html#IDX363"><SAMP>`netstat'</SAMP> network statistics</A><LI><A HREF="unix.html#IDX858">Network byte order</A><LI><A HREF="unix.html#IDX872">Network databases</A><LI><A HREF="unix.html#IDX871">Network information service</A><LI><A HREF="unix.html#IDX24">Never do in unix</A><LI><A HREF="unix.html#IDX887">NFS and C support</A><LI><A HREF="unix.html#IDX870">NIS</A><LI><A HREF="unix.html#IDX71">nobody</A><LI><A HREF="unix.html#IDX608"><CODE>noclobber</CODE> overwrite protection</A><LI><A HREF="unix.html#IDX606"><CODE>noclobber</CODE> variable</A><LI><A HREF="unix.html#IDX379"><SAMP>`nslookup'</SAMP> command</A></DIR><H2>o</H2><DIR><LI><A HREF="unix.html#IDX747"><SAMP>`open'</SAMP> command in perl</A><LI><A HREF="unix.html#IDX828"><CODE>opendir</CODE> command</A><LI><A HREF="unix.html#IDX848">Opening a pipe in C</A><LI><A HREF="unix.html#IDX372">Operating system name</A><LI><A HREF="unix.html#IDX646">Operators in csh</A><LI><A HREF="unix.html#IDX620">Output to file</A><LI><A HREF="unix.html#IDX605">Output, sending to a file</A></DIR><H2>p</H2><DIR><LI><A HREF="unix.html#IDX418">Painting program</A><LI><A HREF="unix.html#IDX526">Panic button</A><LI><A HREF="unix.html#IDX758">Parameters in perl functions</A><LI><A HREF="unix.html#IDX852">Parser</A><LI><A HREF="unix.html#IDX675">Parts of a filename</A><LI><A HREF="unix.html#IDX762"><TT>`passwd'</TT> file</A><LI><A HREF="unix.html#IDX706"><SAMP>`paste'</SAMP></A><LI><A HREF="unix.html#IDX752">Paste as a perl script</A><LI><A HREF="unix.html#IDX277"><SAMP>`paste'</SAMP> command</A><LI><A HREF="unix.html#IDX113">path</A><LI><A HREF="unix.html#IDX34"><CODE>PATH</CODE></A><LI><A HREF="unix.html#IDX35"><CODE>path</CODE></A><LI><A HREF="unix.html#IDX773">Pattern matching in perl</A>, <A HREF="unix.html#IDX778">Pattern matching in perl</A><LI><A HREF="unix.html#IDX774">Pattern replacement in perl</A><LI><A HREF="unix.html#IDX9">PC windows</A><LI><A HREF="unix.html#IDX104">Peers</A><LI><A HREF="unix.html#IDX5">perl</A><LI><A HREF="unix.html#IDX702">Perl</A><LI><A HREF="unix.html#IDX707">Perl variables and types</A><LI><A HREF="unix.html#IDX716">Perl, strings and scalar</A><LI><A HREF="unix.html#IDX754">Perl, truncating strings</A><LI><A HREF="unix.html#IDX460">Permissions on files</A><LI><A HREF="unix.html#IDX840">Permissions, determining in C</A><LI><A HREF="unix.html#IDX355"><SAMP>`PHP'</SAMP></A><LI><A HREF="unix.html#IDX206"><SAMP>`pico'</SAMP></A><LI><A HREF="unix.html#IDX410">Picture processing</A><LI><A HREF="unix.html#IDX316"><SAMP>`pine'</SAMP> mailer</A><LI><A HREF="unix.html#IDX614">Pipe</A><LI><A HREF="unix.html#IDX496">Pipes</A>, <A HREF="unix.html#IDX595">Pipes</A><LI><A HREF="unix.html#IDX847">Pipes in C</A><LI><A HREF="unix.html#IDX616">Piping to more to prevent scrolling</A><LI><A HREF="unix.html#IDX846"><CODE>popen()</CODE></A><LI><A HREF="unix.html#IDX794">POSIX standard</A><LI><A HREF="unix.html#IDX394">Postscript viewers</A><LI><A HREF="unix.html#IDX248">Printer queue</A><LI><A HREF="unix.html#IDX249">Printer status</A><LI><A HREF="unix.html#IDX239"><SAMP>`PRINTER'</SAMP> variable</A><LI><A HREF="unix.html#IDX245">Printing a file</A><LI><A HREF="unix.html#IDX611">Printing multiple lines</A><LI><A HREF="unix.html#IDX569">Procedures and subroutines in Bash</A><LI><A HREF="unix.html#IDX524">Process. moving to background</A><LI><A HREF="unix.html#IDX514">Processes</A><LI><A HREF="unix.html#IDX491">Prompt, redefining</A>, <A HREF="unix.html#IDX583">Prompt, redefining</A><LI><A HREF="unix.html#IDX607">Protecting files from overwrite with <SAMP>`&#62;'</SAMP></A><LI><A HREF="unix.html#IDX466">Protection bits</A><LI><A HREF="unix.html#IDX359"><SAMP>`ps'</SAMP> command</A></DIR><H2>r</H2><DIR><LI><A HREF="unix.html#IDX830"><CODE>readdir</CODE> command</A><LI><A HREF="unix.html#IDX836"><CODE>readlink()</CODE></A><LI><A HREF="unix.html#IDX865"><CODE>recv()</CODE></A><LI><A HREF="unix.html#IDX565">Redefining list separator in Bash</A><LI><A HREF="unix.html#IDX603">Redirection of stdio</A><LI><A HREF="unix.html#IDX139">Regular expressions</A><LI><A HREF="unix.html#IDX869">Reliable socket protocol</A><LI><A HREF="unix.html#IDX217">Renaming files</A><LI><A HREF="unix.html#IDX664"><CODE>repeat</CODE></A><LI><A HREF="unix.html#IDX159">Result of a command into a string</A><LI><A HREF="unix.html#IDX535">Return codes</A><LI><A HREF="unix.html#IDX192"><SAMP>`rlogin'</SAMP></A><LI><A HREF="unix.html#IDX442">rlogin program</A><LI><A HREF="unix.html#IDX226"><SAMP>`rm'</SAMP> command</A><LI><A HREF="unix.html#IDX318"><SAMP>`rmail'</SAMP> in emacs</A><LI><A HREF="unix.html#IDX235"><SAMP>`rmdir'</SAMP> command</A><LI><A HREF="unix.html#IDX47">Role of C in unix</A><LI><A HREF="unix.html#IDX574">Root privileges</A><LI><A HREF="unix.html#IDX69">root user</A><LI><A HREF="unix.html#IDX56">rpcgen</A><LI><A HREF="unix.html#IDX365"><SAMP>`rpcinfo'</SAMP></A><LI><A HREF="unix.html#IDX194"><SAMP>`rsh'</SAMP></A></DIR><H2>s</H2><DIR><LI><A HREF="unix.html#IDX475">s-bit</A>, <A HREF="unix.html#IDX484">s-bit</A><LI><A HREF="unix.html#IDX714">Scalar variables in perl</A><LI><A HREF="unix.html#IDX357">scheme</A><LI><A HREF="unix.html#IDX190"><SAMP>`screen'</SAMP></A><LI><A HREF="unix.html#IDX457">Screens</A><LI><A HREF="unix.html#IDX782">Script aliases in W3</A><LI><A HREF="unix.html#IDX621">Script, making</A><LI><A HREF="unix.html#IDX528">Scripts in Bash, making</A><LI><A HREF="unix.html#IDX775">Searching and replacing in perl (example)</A><LI><A HREF="unix.html#IDX772"><SAMP>`sed'</SAMP> as a perl script</A><LI><A HREF="unix.html#IDX703"><SAMP>`sed'</SAMP> batch editor</A><LI><A HREF="unix.html#IDX279"><SAMP>`sed'</SAMP> editor</A><LI><A HREF="unix.html#IDX657"><SAMP>`sed'</SAMP>, search and replace</A><LI><A HREF="unix.html#IDX864"><CODE>send()</CODE></A><LI><A HREF="unix.html#IDX302">Sending messages</A><LI><A HREF="unix.html#IDX584"><CODE>set</CODE> command</A><LI><A HREF="unix.html#IDX586"><CODE>setenv</CODE> command</A><LI><A HREF="unix.html#IDX477">setgid bit</A><LI><A HREF="unix.html#IDX490">Setting the prompt</A>, <A HREF="unix.html#IDX582">Setting the prompt</A><LI><A HREF="unix.html#IDX581">Setting up the C shell</A><LI><A HREF="unix.html#IDX449">Setting up the x environment</A><LI><A HREF="unix.html#IDX476">setuid bit</A><LI><A HREF="unix.html#IDX573">SetUID scripts</A><LI><A HREF="unix.html#IDX40"><TT>`sh'</TT></A><LI><A HREF="unix.html#IDX178">sh</A><LI><A HREF="unix.html#IDX179">sh5</A><LI><A HREF="unix.html#IDX808">Shared libraries</A><LI><A HREF="unix.html#IDX4">shell</A>, <A HREF="unix.html#IDX32">shell</A>, <A HREF="unix.html#IDX37">shell</A><LI><A HREF="unix.html#IDX51">Shell commands and C library calls</A><LI><A HREF="unix.html#IDX173"><KBD>Shells, various</KBD></A><LI><A HREF="unix.html#IDX186"><SAMP>`shelltool'</SAMP></A><LI><A HREF="unix.html#IDX725"><SAMP>`shift'</SAMP> and arrays</A><LI><A HREF="unix.html#IDX724"><SAMP>`shift'</SAMP> and arrays in perl</A><LI><A HREF="unix.html#IDX534"><CODE>shift</CODE> operator on strings</A><LI><A HREF="unix.html#IDX367"><SAMP>`showmount'</SAMP></A><LI><A HREF="unix.html#IDX570">Signal handler in Bash</A><LI><A HREF="unix.html#IDX502">Single and double quotes</A><LI><A HREF="unix.html#IDX700"><SAMP>`sleep'</SAMP> command</A><LI><A HREF="unix.html#IDX862"><CODE>socket()</CODE></A><LI><A HREF="unix.html#IDX854">Sockets</A><LI><A HREF="unix.html#IDX94">Soft links</A><LI><A HREF="unix.html#IDX436"><SAMP>`Sonar'</SAMP> ping</A><LI><A HREF="unix.html#IDX430">Spelling checker</A><LI><A HREF="unix.html#IDX727"><SAMP>`split'</SAMP> and arrays</A><LI><A HREF="unix.html#IDX726"><SAMP>`split'</SAMP> command</A><LI><A HREF="unix.html#IDX792">Splitting C into many files.</A><LI><A HREF="unix.html#IDX618">Splitting output to several files</A><LI><A HREF="unix.html#IDX60">Standard error</A><LI><A HREF="unix.html#IDX495">Standard I/O in Bash</A><LI><A HREF="unix.html#IDX746">Standard I/O in perl</A><LI><A HREF="unix.html#IDX604">Standard I/O, redirection</A><LI><A HREF="unix.html#IDX58">Standard input</A><LI><A HREF="unix.html#IDX59">Standard output</A><LI><A HREF="unix.html#IDX842">Starting</A><LI><A HREF="unix.html#IDX516">Starting shell jobs</A><LI><A HREF="unix.html#IDX834"><CODE>stat()</CODE></A><LI><A HREF="unix.html#IDX807">Static linking</A><LI><A HREF="unix.html#IDX833">Statistics about a file</A><LI><A HREF="unix.html#IDX483">Sticky bit</A><LI><A HREF="unix.html#IDX715">Strings in perl</A><LI><A HREF="unix.html#IDX764"><SAMP>`stty'</SAMP> and switching off term echo</A><LI><A HREF="unix.html#IDX756">Subroutines in perl</A><LI><A HREF="unix.html#IDX631">Subshells and ()</A><LI><A HREF="unix.html#IDX812">Suffix rules in Makefiles</A><LI><A HREF="unix.html#IDX70">superuser</A><LI><A HREF="unix.html#IDX521">Suspending a job</A><LI><A HREF="unix.html#IDX658">Swapping text strings</A><LI><A HREF="unix.html#IDX637"><CODE>switch..case</CODE> in csh</A><LI><A HREF="unix.html#IDX95">Symbolic links</A><LI><A HREF="unix.html#IDX13">System 5</A><LI><A HREF="unix.html#IDX370"><SAMP>`System details'</SAMP></A><LI><A HREF="unix.html#IDX656">System identity and <SAMP>`uname'</SAMP></A><LI><A HREF="unix.html#IDX373">System name</A><LI><A HREF="unix.html#IDX12">System V</A></DIR><H2>t</H2><DIR><LI><A HREF="unix.html#IDX485">t-bit</A><LI><A HREF="unix.html#IDX501"><KBD>TAB</KBD> completion key</A><LI><A HREF="unix.html#IDX308"><SAMP>`talk'</SAMP> service</A><LI><A HREF="unix.html#IDX353"><SAMP>`TCL'</SAMP></A><LI><A HREF="unix.html#IDX855">TCP/IP</A><LI><A HREF="unix.html#IDX44">tcsh</A>, <A HREF="unix.html#IDX180">tcsh</A><LI><A HREF="unix.html#IDX617"><SAMP>`tee'</SAMP> command</A><LI><A HREF="unix.html#IDX440">Teletype terminal</A><LI><A HREF="unix.html#IDX102">telnet</A><LI><A HREF="unix.html#IDX196"><SAMP>`telnet'</SAMP></A><LI><A HREF="unix.html#IDX765">Terminal echo and <SAMP>`stty'</SAMP></A><LI><A HREF="unix.html#IDX182">Terminals</A><LI><A HREF="unix.html#IDX557"><SAMP>`test'</SAMP> in Bash</A><LI><A HREF="unix.html#IDX28">test programs</A><LI><A HREF="unix.html#IDX29">test, don't call your program this</A><LI><A HREF="unix.html#IDX638">Testing files</A><LI><A HREF="unix.html#IDX438">Testing response from other hosts.</A><LI><A HREF="unix.html#IDX635">Tests and conditions in csh</A><LI><A HREF="unix.html#IDX537">Tests in Bash</A><LI><A HREF="unix.html#IDX396"><SAMP>`tex'</SAMP></A><LI><A HREF="unix.html#IDX401"><SAMP>`texinfo'</SAMP> system</A><LI><A HREF="unix.html#IDX470">Text form of access bits</A><LI><A HREF="unix.html#IDX395">Text formatting</A><LI><A HREF="unix.html#IDX210"><SAMP>`textedit'</SAMP></A><LI><A HREF="unix.html#IDX819">The argument vector in C</A><LI><A HREF="unix.html#IDX882">The domain name service</A><LI><A HREF="unix.html#IDX415">tiff</A><LI><A HREF="unix.html#IDX429">Time and date</A><LI><A HREF="unix.html#IDX223">Time stamp, updating</A><LI><A HREF="unix.html#IDX787">Tk library</A><LI><A HREF="unix.html#IDX220"><SAMP>`touch'</SAMP> command</A><LI><A HREF="unix.html#IDX572">Traps in Bash</A><LI><A HREF="unix.html#IDX753">Truncating strings in perl</A><LI><A HREF="unix.html#IDX439">tty</A><LI><A HREF="unix.html#IDX256"><SAMP>`type'</SAMP> in DOS</A><LI><A HREF="unix.html#IDX708">Types in perl</A></DIR><H2>u</H2><DIR><LI><A HREF="unix.html#IDX474"><CODE>umask</CODE> variable</A>, <A HREF="unix.html#IDX478"><CODE>umask</CODE> variable</A><LI><A HREF="unix.html#IDX655"><SAMP>`uname'</SAMP> command</A><LI><A HREF="unix.html#IDX591">Undefining variables</A><LI><A HREF="unix.html#IDX25">undelete</A><LI><A HREF="unix.html#IDX1">UNIX</A><LI><A HREF="unix.html#IDX2">UNIX history</A><LI><A HREF="unix.html#IDX735"><SAMP>`unless'</SAMP> in perl</A><LI><A HREF="unix.html#IDX228"><SAMP>`unlink'</SAMP> command</A><LI><A HREF="unix.html#IDX590"><CODE>unset</CODE> command</A><LI><A HREF="unix.html#IDX563"><SAMP>`until'</SAMP></A><LI><A HREF="unix.html#IDX498">Up arrow</A><LI><A HREF="unix.html#IDX225">Updating file time stamp</A><LI><A HREF="unix.html#IDX771">User database support</A><LI><A HREF="unix.html#IDX106">User environment</A><LI><A HREF="unix.html#IDX294"><SAMP>`users'</SAMP> command</A></DIR><H2>v</H2><DIR><LI><A HREF="unix.html#IDX126">Variables, global</A><LI><A HREF="unix.html#IDX128">Variables, local</A><LI><A HREF="unix.html#IDX200"><SAMP>`vi'</SAMP></A><LI><A HREF="unix.html#IDX254">Viewing a file</A><LI><A HREF="unix.html#IDX361"><SAMP>`vmstat'</SAMP> virtual memory stats</A></DIR><H2>w</H2><DIR><LI><A HREF="unix.html#IDX300"><SAMP>`w'</SAMP> command</A><LI><A HREF="unix.html#IDX844"><TT>`wait.h'</TT></A><LI><A HREF="unix.html#IDX843">Waiting for child processes</A><LI><A HREF="unix.html#IDX287"><SAMP>`whereis'</SAMP> command</A><LI><A HREF="unix.html#IDX115">which command</A><LI><A HREF="unix.html#IDX665"><CODE>while</CODE></A><LI><A HREF="unix.html#IDX562"><SAMP>`while'</SAMP> in Bash</A><LI><A HREF="unix.html#IDX736"><SAMP>`while'</SAMP> in perl</A><LI><A HREF="unix.html#IDX533"><CODE>while</CODE> loop in Bash</A><LI><A HREF="unix.html#IDX298"><SAMP>`who'</SAMP> command</A><LI><A HREF="unix.html#IDX699"><SAMP>`whoami'</SAMP> command</A><LI><A HREF="unix.html#IDX112">Wildcards</A>, <A HREF="unix.html#IDX131">Wildcards</A><LI><A HREF="unix.html#IDX3">Windows</A><LI><A HREF="unix.html#IDX7">Windows on PC</A><LI><A HREF="unix.html#IDX49">Wrapper functions</A><LI><A HREF="unix.html#IDX784">Wrappers</A><LI><A HREF="unix.html#IDX304"><SAMP>`write'</SAMP> command</A><LI><A HREF="unix.html#IDX630"><CODE>write</CODE> example</A><LI><A HREF="unix.html#IDX623">Writing a script</A><LI><A HREF="unix.html#IDX845"><CODE>WTERMSIG(status)</CODE></A></DIR><H2>x</H2><DIR><LI><A HREF="unix.html#IDX456">X access control</A><LI><A HREF="unix.html#IDX445">X display</A>, <A HREF="unix.html#IDX451">X display</A><LI><A HREF="unix.html#IDX444">X protocol</A><LI><A HREF="unix.html#IDX443">X window system</A><LI><A HREF="unix.html#IDX786">X windows</A><LI><A HREF="unix.html#IDX453">X windows access</A><LI><A HREF="unix.html#IDX452">X windows authentification</A><LI><A HREF="unix.html#IDX108">X-windows</A><LI><A HREF="unix.html#IDX386"><SAMP>`xarchie'</SAMP> client</A><LI><A HREF="unix.html#IDX455">Xauthority mechanism</A><LI><A HREF="unix.html#IDX208"><SAMP>`xedit'</SAMP></A><LI><A HREF="unix.html#IDX204"><SAMP>`xemacs'</SAMP></A><LI><A HREF="unix.html#IDX419"><SAMP>`xfig'</SAMP> drawing program</A><LI><A HREF="unix.html#IDX454">xhost mechanism</A><LI><A HREF="unix.html#IDX416"><SAMP>`xpaint'</SAMP> program</A>, <A HREF="unix.html#IDX422"><SAMP>`xpaint'</SAMP> program</A><LI><A HREF="unix.html#IDX388"><SAMP>`xrn'</SAMP> news reader</A><LI><A HREF="unix.html#IDX184"><SAMP>`xterm'</SAMP></A><LI><A HREF="unix.html#IDX441">xterm program</A><LI><A HREF="unix.html#IDX411"><SAMP>`xv'</SAMP> picture processor</A><LI><A HREF="unix.html#IDX350"><SAMP>`xxgdb'</SAMP></A></DIR><H2>y</H2><DIR><LI><A HREF="unix.html#IDX789"><SAMP>`yacc'</SAMP></A>, <A HREF="unix.html#IDX853"><SAMP>`yacc'</SAMP></A><LI><A HREF="unix.html#IDX55">yacc</A></DIR><H2>z</H2><DIR><LI><A HREF="unix.html#IDX320"><SAMP>`zmail'</SAMP> client</A><LI><A HREF="unix.html#IDX181">zsh</A></DIR><H2>|</H2><DIR><LI><A HREF="unix.html#IDX596"><SAMP>`|'</SAMP> symbol</A>, <A HREF="unix.html#IDX615"><SAMP>`|'</SAMP> symbol</A></DIR></P><P><HR><P>This document was generated on 23 August 2001 using the<A HREF="http://wwwcn.cern.ch/dci/texi2html/">texi2html</A>translator version 1.51.</P></BODY></HTML>